按照是否独享、共享分为两类:
每个线程都会独有的区域:栈、程序计数器器、本地方法栈
线程共享区域:堆、方法区 ------>线程安全问题
栈:线程独有的东西
栈帧:栈帧分配空间的方式:每次分出一块来给新的方法栈,即便是递归调用;--> 如果方法一直增加,可能会导致栈溢出
程序计数器:每个线程都有的一块内存空间,存放程序将要运行的内存位置(指针位置);
主要是用于多线程场景下记录程序挂起前的执行位置,便于恢复执行后使用;
动态链接:在程序运行期间,把符号引用转换为对应的代码的内存地址;(静态链接:程序加载的过程中)
方法出口:方法执行完成后要回到main方法中的位置
局部变量表:存放对象在堆中存放的内存位置;
操作数栈:临时存放操作数(变量对应的值)的内存
方法区:常量、静态变量(对象类型存放的还是指针)、类信息;
堆:new出来的对象
年轻代(Eden、Survivor)--三分之一、老年代---三分之二左右;
存储到释放的流程:
new出来的对象一般先放到Eden区域,至Eden区域放满之后,JVM调用GC---minor gc 把Eden区域中没有引用的对象回收掉,
假如有引用,会把对象放到Survivor,这是年龄会加1;当年龄增加至15时,会移至老年代区域中.。
当老年代中存满之后会先触发fullgc,fullgc会回收整个对堆和方法区(共享区域),假如无法回收会触发OOM
(整个过程可以使用JDK自带的工具-jvisualvm查看;gc流程:minor gc --->full gc)
STW:在gc的过程中会触发STW(stop the world)机制,停止用户发起的线程--->页面上显示的就是卡顿;
STW的原因:防止在gc的过程中一些对象由非垃圾对象变为垃圾对象
JVM调优主要就是减少full gc,因为她占用的时间比较长,处罚STW的时间也会比较长;
springboot 启动参数 设置方法区内、栈等等存大小
-Xss: 栈内存空间值越小,一个线程栈里面可以分配的栈帧就越少;
但是对于JVM来说可以开启的线程数就越多(总的内存资源是有限的,独享区域占用越少,总的数量就会越多);