一.介绍
gc基本原理:队对象的分配和释放。
Full GC:针对新生代Young Gen,老年代Tenured Gen,永久代Perm Gen(1.7),元空间metaspace(1.8)全范围的gc。
永久代和元空间的区别:(1)永久代属于堆内存的一部分;而元空间为本地内存。
(2)永久代存储Class信息,常量,静态变量等数据,而元空间存储类的元数据。
各类垃圾回收器:(1)Serial GC:Serial Young GC + Serial Old GC,实际上是Full GC。
(2)Parallel GC:Parallel Young GC + 非并行的PS MarkSweep GC / 并行的Parallel Old GC,实际上也是
Full GC;选PS MarkSweep GC 还是 Parallel Old GC 由参数UseParallelOldGC来控制。
(3)CMS GC:ParNew(Young)GC + CMS(Old)GC + Full GC;使用标记-清除算法。
(4)G1 GC:Young GC + mixed GC+ Full GC;使用标记-整理算法。
空间分配担保:在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次Minor GC,尽管这次Minor GC有风险;如果小于,或者不允许担保失败,那这是也要改为一次老年代垃圾回收。
finalize():对象在被gc时会自救一次,若对象覆盖finalize()方法,会被系统自动调用实现自救,否则直接回收。
二.触发场景
1.eden区满了,jvm允许担保失败,若存活进入老年代的对象大小<老年代剩余空间,会触发Minor GC。
2.eden区满了,jvm不允许担保失败或者存活进入老年代的对象大小>老年代剩余空间,会触发Full GC。
3.调用System.gc(),并不一定触发的Full GC。
4.老年代区满了,进行Full GC,gc后如果空间仍然不足,会抛出Java.lang.OutOfMemoryError。
5.未使用CMS收集器进行gc时,永久代满了,会触发Full GC。
三.如何进行gc排查
1.排查分析:(1)检查gc各分代区使用情况。(2)查看gc日志,检查各类gc的触发频率。
2.解决方式:(1)优化代码,如减少大对象,大数组的创建;引用对象不再使用后赋值为null等。
(2)调整堆区的大小,CMS的话设置触发堆空间gc的比例。
(3)调节jvm参数配置回收机制。
四.gc算法
1.引用计数算法:有对象之间循环依赖问题。
2.可达性分析算法:GC root作为起点,判断对象是否与之相连,不相连视为不可达。
回收算法:复制算法,标记整理,标记清除,分代回收算法。
五.年轻代jvm参数设置(转载https://blog.csdn.net/jisuanjiguoba/article/details/80156781)
1)-XX:NewSize和-XX:MaxNewSize
用于设置年轻代的大小,建议设为整个堆大小的1/3或者1/4,两个值设为一样大。
2)-XX:SurvivorRatio
用于设置Eden和其中一个Survivor的比值,这个值也比较重要。
3)-XX:+PrintTenuringDistribution
这个参数用于显示每次Minor GC时Survivor区中各个年龄段的对象的大小。
4).-XX:InitialTenuringThreshol和-XX:MaxTenuringThreshold
用于设置晋升到老年代的对象年龄的最小值和最大值,每个对象在坚持过一次Minor GC之后,年龄就加1。