常见的GC
| 年轻代 | 老年代 | 说明 |
|---|---|---|
| Serial | Serial Old | 单线程 |
| ParNew | CMS | 低延迟(已淘汰) |
| Parallel | Parallel Old | 高吞吐 |
| G1 | G1 | 默认推荐 |
| ZGC | ZGC | 极低延迟 |
G1和ZGC有啥区别?
G1 GC在JDK7u4引入,JDK9成为默认垃圾收集器;
ZGC 在JDK11引入,最初是实验性的,JDK15 正式转为生产可用
G1部分 STW + Region 回收
ZGC:全程并发压缩,停顿 < 10ms
回收算法的区别?
| G1 | ZGC | |
|---|---|---|
| 算法 | 标记 + 复制 | 并发标记 + 并发压缩 |
| 内存压缩 | STW + 部分并发 | 全程并发 |
| Full GC | 可能发生 | 几乎不存在 |
CMS:核心算法是标记清除算法,流程为初始只会标记GC Roots直接引用的对象,此时会短暂的STW;然后会并发标记,从GC Roots开始遍历整个对象图,应用线程可以同时运行;然后会STW,修正并发阶段对象的引用变化,最后释放不再使用的对象
G1:是JDK9开始默认的垃圾回收器,Garbage First,顾名思意,意味着先处理垃圾最多的地方;G1不在使用的传统的新生代老年代,而是将堆拆分成多个Region,每个Region有GC Roots,然后进行并发标记,并发压缩,并发垃圾回收,最后进行STW,将不再使用的Region释放掉;**-XX:MaxGCPauseMillis=200**通过这个参数可以预测停顿时间,并且因为是复制算法所有不会有内存碎片
ZGC:zgc是超低延迟的GC,核心用的是染色指针的算法,对象的引用关系通过颜色进行标记(引用地址 + GC状态位);jdk9及以后后默认是G1, ZGC是jdk11开始实验性的发布的,到jdk17 zgc才在生产稳定可用;如果要将G1修改为ZGC,需要设置-XX:+UseZGC
ZGC 的 Load Barrier 和 G1 的 Write Barrier 有什么区别?
G1主要使用 Write Barrier,在对象引用被修改时记录跨 Region 的引用关系,并维护 Remembered Set,用于减少 GC 时的扫描范围。
而ZGC使用 Load Barrier,在读取对象引用时检查对象是否已经被GC线程移动,如果已经移动则修正引用地址。
G1的Barrier主要用于维护引用关系,而ZGC的Barrier主要用于支持对象的并发移动
ZGC为啥不能用32位的机子?
ZGC的实现基于64位虚拟机,32位机子无法支持ZGC;因为ZGC用了染色指针的算法,所以需要单独存GC的状态位,32位的机子最大为4G如果引用地址很多的话,那么将无法存储状态位,就会导致GC无法进行;所以ZGC也需要大内存,一般16G或32G以上