现代垃圾收集器大部分基于分代收集理论设计,堆空间细分为:
使用下面命令设置堆空间初始化 10m,最大空间 10m
-Xms10m -Xmx10m
使用java visual 查看 visual gc
可以看出通过参数设置的内存大小 只与新生代(Eden+s0+s1 ),老年代有关,而在逻辑上还要加上元空间。
-Xms 用来设置堆空间(年轻代+老年代)的初始内存大小 -X 是jvm的运行参数 ms 是memory start -Xmx 用来设置堆空间(年轻代+老年代)的初始内存大小
使用一下代码查看 当前jvm初始化内存与最大内存
/** * @program: jvmDemo * @description: * @author: wfg * @create: 2021-06-14 10:40 */ public class Test9 { public static void main(String[] args) { //返回jvm中的内存总量(字节) long initialMemory = Runtime.getRuntime().totalMemory()/1024/1024; //虚拟机将尝试使用最大堆内存 long maxMemory = Runtime.getRuntime().maxMemory()/1024/1024; System.out.println("-Xms:"+initialMemory+"m"); System.out.println("-Xmx:"+maxMemory+"m"); System.out.println("系统大小:"+initialMemory*64/1024+"G"); System.out.println("系统大小:"+maxMemory*4/1024+"G"); } }
结果(本机运行内存为 8g)
设置300
查看
/** * @program: jvmDemo * @description: * @author: wfg * @create: 2021-06-14 10:40 */ public class Test9 { public static void main(String[] args) { //返回jvm中的内存总量(字节) long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024; //虚拟机将尝试使用最大堆内存 long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024; System.out.println("-Xms:" + initialMemory + "m"); System.out.println("-Xmx:" + maxMemory + "m"); } }
结果
分析
在vm参数设置里面加上
-XX:+PrintGCDetails
再次运行程序查看
原理
新生代的s0 和 s1 只能有一个生效
一类是生命周期较短的瞬时对象。
另外一类是对象生命周期非常长。
可以通过 -XX:NewRation
设置新生代与老年代的比例,默认值是2.(一般都不会去设置)
1.new的对象先放伊甸区,此区有大小限制
2.当伊甸区满的时候,程序需要创建时,jvm的垃圾回收将对伊甸园区进行垃圾回收(minor gc)
3.然后将伊甸园中的剩余对象移动到辛存者0
4.如果再次触发垃圾回收,上次幸存下来的放到幸存者0区,没有回收,就会放到幸存者1区
5.再次经历垃圾回收会重新放回辛存者0区
6.当在辛存者区达到15次时,就可以去老年区了
可以设置参数:-XX:MaxTenuringThreshold=
7.当养老区内存不足时,再次触发GC:major GC,进行养老区的内存处理
8.若养老区进行处理后,依然无法进行对象的保存,就会产生00m异常
java.lang.outofMemoryError:java heap space
9.总结
10.流程
当Eden满时,会触发MinorGC算法来回收memory,旨在清理掉再无引用的数据(在内存里是Tree),意图存储到S0. 若此时S0也满了,会再次MinorGC意图回收S0无引用的数据,把有引用的数据移动到S1。如果S1够用,此时会清空S0;如果S1满了,会回滚刚存入S1的数据,直接把本次GC的数据存入Old区,S0保持刚刚MinorGC时的状态。延伸:如果Old也满了,会触发MajorGC,如果还是不够,则存入Permanent Generate,不幸这里也满了,会在允许的范围内按照内置的规则自动增长,可能不会发生GC,也可能会。当增长的量不够存时,会触发Full GC。若FullGC后还是不够存,自动增长的量也超过了允许的范围,则发生内存溢出。还有一种情况,就是分配的线程栈处于很深的递归或死循环时,会发生栈内存溢出。
-XX:UseTLAB
设置是否开启(默认是开启的)-XX:TLABWasteTargetPercent
设置tlab空间所占用eden空间的大小对象分配流程
-XX:+PrintFlagsInitial
: 查看所有参数的默认初始值-XX:+PrintFlagFinal
: 查看所有参数的最终值-Xms:
:初始化堆空间内存(默认为物理内存的1/64)-Xmx
: 最大堆空间内存(默认为物理内存的1/4)-Xmn
:设置新生代的大小(初始值及最大值)-XX:NewRatio
: 配置新生代与老年代在堆结构的占比-XX:SurvivorRatio
:设置新生代中 eden和s0、s1空间的比例-XX:MaxTenuringThreshold
:设置新生代垃圾最大的年龄-XX:+PrintGCDetails
:输出详细的gc处理日志-
XX:+PrintGC
:输出简要的gc处理日志判断逃逸的方法:看new 的对象实体是否有可能在方法外被调用