一、GC算法
1.标记-清除算法(Mark Sweep): 缺:效率低、有内存碎片
a.标记阶段:遍历所有GC roots,将gc roots引用链可达的对象标记为存活;
b.清理阶段:遍历堆中所有对象,清理未被标记的对象。
2.复制算法:先根据引用链做可达性分析,把活着的对象复制过去,然后把原区域清空。
优:解决内碎片问题;存活率低时效率高
缺:浪费内存;对象存活率高时效率低下
3.标记-整理算法:移动所有存活对象,按地址排序,把后面的清除。 效率也不高
4.分代收集:新生代采用复制算法(存活率低)、老年代采用标记整理算法(存活率高)。
原因:大部分对象的生命周期很短,极少部分可能会存活很久,这部分对象每次gc反复标记处理,浪费资源。
5.判断是不是垃圾: 引用记数法(循环引用时内存泄露);
可达性分析:从gc roots开始通过引用关系遍历对象图,能被引用链遍历到的认为存活(基本都是用这种方式)
6.GC roots:引用链的最顶级,是一组必须活跃的引用,不是对象! minor gc比full gc的gc roots还要更多,因为要从old gen里面额外拿gc roots. gc roots有哪些: a.活跃的栈帧中的引用对象; b.方法区中静态属性指向堆中对象的引用; c.本地方法栈中JNI(native方法)的引用
7.stop-the-world:gc的时候,停掉除gc外的java线程。
二、gc收集器
1. Serial / Serial old:单线程;复制算法 / 标记整理算法;停顿时间长
ParNew:多线程;新生代的复制算法
Parallel Scavenge / Parallel old:多线程(paralle:并行),复制算法 / 标记整理算法;注重吞吐量: T运行 / (T运行+Tgc)
CMS:多线程;老年代的标记m清除s算法; 优:停顿时间短; 缺:吃cpu资源,有内存碎片,清理阶段会产生新垃圾(浮动垃圾)
cms执行过程: 1.STW标记gc roots引用的对象; 2.和用户线程一起并发标记其他对象;
3.STW标记第二步新增的对象; 4.和用户线程一起并发清理垃圾。
G1:区域化、并发、增量式垃圾回收器。 整体看是标记整理,局部(两个region之间)是复制算法。
引入分区的思路,弱化了分代的概念。 整个堆内存被分为许多大小相等的连续区域Region,维护一个优先列表,记录每个Region的价值,价值是由之前这个区域GC所获空间大小和GC所需时间来决定的(优先列表类似逻辑上的新生代/老年代?)。
工作过程类似CMS,第四步清理有区别(根据优先级控制时间),增加remembered set保存对象引用的调用信息;
最后一步的清理阶段基于标记-整理和复制算法实现。
优:性能好、无碎片、G1的gc耗时可控:根据预设的gc耗时,优先回收高价值的region.
2.G1和CMS的对比: 1.G1无内存碎片,CMS有 2.G1的gc时间可控 3.CMS只回收老年代,G1无物理分代
3.JDK11中的ZGC:专注于减少暂停时间的同时压缩堆。 优:无分代概念、无碎片、时间可控、停顿时间跟堆大小没关系
a.并发执行的保证机制,就是Colored Pointer(着色指针:将信息存储在指针/引用上) 和 Load Barrier(读屏障)
b.像G1一样划分Region,但更加灵活:g1的region大小固定,ZGC 可以有2MB,32MB,N× 2MB,大对象放大region
c. STW标记gcRoots(此操作不标记堆中的对象,所以停顿时间跟堆大小没关系,但是跟线程数量和线程内对象数量有关); 并发标记; 复制到另一个region(老区域可以成为新的复制to区); Remap修正指针:将指针都指向新地址(上一阶段的Remap和下一阶段的Mark是同时操作的,节省遍历图的开销);
d. 没有g1的RememberSet和写屏障的开销:划分Region并不是为了增量回收,每次都会对所有Region进行回收,所以也就不需要这个占内存的RememberSet了;又因为它暂时没有分代,所以完全没有Write Barrier。
三、为什么要关注gc?
知道垃圾是怎么回收的,写代码的时候减少长生命周期对象的使用、减少大对象的创建;监控如果频繁gc则要快速定位原因balabala..
四、线上频繁full gc怎么办?
查看gc日志判断gc原因;合理调参分配各个区域的大小;增加Survivor区来防止更多的对象进入老年代
五、线上用的:
G1: 堆总内存:12G
Eden区:0~8G;
OldGen:1~6G;
survivor区:平均100多M;
元空间metaSpace: 平均100多M;
频率: youngGC:每分钟0~2次,每次100ms左右.(在做youngGC时,OldGen区域也会相应减少,因为G1没有物理分区新生代老年代) 没有fullGC