G1日志
G1有详细的日志信息,建议使用下面的参数,当G1出问题,可以获取很多有用的信息
1、-xx:+PrintGCDateStamps 打印日期和正常云行时间
2、-xx:+PrintGCDetails 打印G1详细信息
3、-xx:+PrintAdaptiveSizePolicy 打印自适应调节策略;自适应策略:GC会根据中统计的GC时间、吞吐量、内存占用量,重新计算堆内存中各区大小
4、-xx:+PrintTenuringDistribution 打印survivor region区域内的对象的age信息
GC过程
1、年轻代GC
1、年轻代收集会,不会进行并发标记,所以它全程都是STW
2、应用线程不断活动后,年轻代空间会被逐渐填满。当JVM分配对象到Eden区域失败(Eden区已满)时,便会触发一次STW式的年轻代收集
工作过程
1、根扫描 Root Scanning:静态和本地对象等被扫描
2、更新已记忆集合 Update RSet:对dirty卡片的分区进行扫描,来更新RSet
3、RSet扫描:在收集当前CSet之前,扫描CSet分区的RSet,检测old->young这种引用情况
4、转移和回收-Object Copy:将CSet分区存活对象的转移到新survivor或old Region,回收CSet内垃圾对象
5、引用处理:主要针对软引用、弱引用、虚引用、final引用、JNI引用;当占用时间过多时,可选择使用参数-XX:+ParallelRefProcEnabled激活多线程引用处理
6、在年轻代收集中,Eden分区存活的对象将被拷贝到Survivor分区;原有Survivor分区存活的对象,将根据对象的年龄而晋升到新的survivor分区和老年代分区。而原有的年轻代分区将被整体回收掉。
2、老年代GC
1、当堆内存占用空间超过整堆比IHOP阈值-XX:InitiatingHeapOccupancyPercent(默认45%)时,G1就会进行年老代收集
1.1、在年轻代收集之后或巨型对象分配之后,会去检查这个空间占比
1.2、年轻代晋升老年代失败会触发老年代GC或者Full GC
2、年老代收集同时会执行年轻代收集,进行年老代的roots探测,既初始标记,STW的过程
3、并发标记
4、重新标记,STW的过程,这个过程使用STAB算法。
5、清除垃圾,STW的过程。
3、混合GC
1、在进行正常的年轻代垃圾收集,也会回收一部分老年代分区。会优先选取垃圾多(垃圾占用大于85%,复制算法存活对象越少效率越高)的Regions,一共1/8的年老代Regions加入Cset中
2、假设一个Region的存活对象达到95%,而进行复制,效率很低,所以G1允许浪费部分内存,那么这个Region不会被混合收集,-XX:G1HeapWastePercent:默认5%
3、stw,然后将Cset中的Regions进行收集,使用复制算法
4、下一次年轻代垃圾收集进行时,在将第二个1/8的年老代Regions加入Cset中进行收集
当年老代内单个Region的垃圾小于等于G1HeapWastePercent时,复制大量存活对象,效率很低。此时G1会确定结束混合收集周期。所以混合收集次数可能小于8次。
4、Full GC
STW式的、单线程的Full GC。Full GC会对整堆做标记清除和压缩,最后将只包含纯粹的存活对象。
总结
具体执行过程中的细节,后面梳理之后再补充~~~~
原文地址:https://blog.51cto.com/janephp/2429303