GC基础知识
1、什么是垃圾
没有任何引用指向的一个对象或者多个对象(循环引用)
2、如何定位垃圾
- 引用计数
- 根可达算法
3、常见的垃圾回收算法
- 标记清除(mark sweep) - 位置不连续 产生碎片 效率偏低(两遍扫描)
- 拷贝算法 (copying) - 没有碎片,浪费空间
- 标记压缩(mark compact) - 没有碎片,效率偏低(两遍扫描,指针需要调整)
4、JVM 内存分配模型
-
部分垃圾回收器使用的模型
- 除Epsilon ZGC Shenandoah之外的GC都是使用逻辑分代模型
- G1是逻辑分代,物理不分代
- 除此之外不仅逻辑分代,而且物理分代
- 新生代 + 老年代 + 永久代(1.7)Perm Generation/ 元数据区(1.8) Metaspace
- 永久代 元数据 - Class
- 久代必须指定大小限制 ,元数据可以设置,也可以不设置,无上限(受限于物理内存)
- 字符串常量 1.7 - 永久代,1.8 - 堆
- MethodArea逻辑概念 - 永久代、元数据
-
新生代 = Eden + 2个suvivor区
- YGC回收之后,大多数的对象会被回收,活着的进入s0
- 再次YGC,活着的对象eden + s0 -> s1
- 再次YGC,eden + s1 -> s0
- 年龄足够 -> 老年代 (15 CMS 6)
- s区装不下 -> 老年代
- 老年代
- 顽固分子
- 老年代满了FGC Full GC
- GC Tuning (Generation)
- 尽量减少FGC
- MinorGC = YGC
- MajorGC = FGC
常见的垃圾回收器
- Serial 年轻代 串行回收
单CPU效率最高,虚拟机是Client模式的默认垃圾回收器。Serial回收器使用单线程进行垃圾回收,使用复制算法。在 HotSpot 虚拟机中,使用-XX:+UseSerialGC 参数可以指定使用Serial(新生代串行收集器)+ Serial Old(老年代串行收集器)。 -
PS 年轻代 并行回收
新生代并行回收收集器也是使用复制算法的收集器。从表面上看,它和并行收集器一样都是多线程、独占式的收集器。但是,并行回收收集器有一个重要的特点:它非常关注系统的吞吐量。
在启动参数中指定-XX:+UseParallelGC,会使用Parallel Scavenge(新生代并行回收收集器) + SerialOld的回收器组合
如果使用-XX:+UseParallelOldGC,表示Parallel Scavenge(新生代并行回收收集器)+ Parallel Old(并行回收收集器) - ParNew 年轻代 配合CMS的并行回收
Serial回收器的多线程版本,只能用于新生代。使用复制算法,多线程并行工作。在多CPU主机上的性能高于Serial,单CPU主机上的性能低于Serial。
如果使用-XX:+UseParNewGC,表示ParNew(并行收集器)+ Serial Old(串行收集器)
- SerialOld老年代 串行回收
Serial收集器的老年版本,独占式,单线程,使用的是标记--整理算法,这个收集器的目的也是用于Client模式下的虚拟机使用。
- ParallelOld老年代 并行回收
是Parallel Scavenge收集器的老年版本,使用多线程和标记整理算法,注重吞吐量优先,在注重吞吐量和CPU资源铭感的场合,都可以考虑Parallel Scavenge加Parallel Old收集器。
- ConcurrentMarkSweep 老年代 并发的, 垃圾回收和应用程序同时运行,降低STW的时间(200ms)
算法:三色标记 + Incremental Update
1.初始标记:Stop the world,只标记GC Roots能直接关联到的对象。
2.并发标记:GC Roots Tracing
3.重新标记:Stop the world,修正并发标记期间,因用户程序继续运行导致标记产生变动的那一部分对象的标记记录。
4.并发清除:并发清除可以和用户线程一起运行,所以总体上停顿的时间非常短。
但是CMS收集器有三个显著缺点:
1.对CPU资源敏感。
2.无法处理浮动垃圾。
3.收集结束后会产生大量碎片。
- G1 (10ms) 算法:三色标记 + SATB
1.G1的设计原则是"首先收集尽可能多的垃圾(Garbage First)"。因此,G1并不会等内存耗尽(串行、并行)或者快耗尽(CMS)的时候开始垃圾收集,而是在内部采用了启发式算法,在老年代找出具有高收集收益的分区进行收集。同时G1可以根据用户设置的暂停时间目标 自动调整年轻代和总堆大小,暂停目标越短年轻代空间越小、总空间就越大;
2.G1采用内存分区(Region)的思路,将内存划分为一个个相等大小的内存分区,回收时则以分区为单位进行回收,存活的对象复制到另一个空闲分区中。由于都是以相等大小的分区为单位进行操作,因此G1天然就是一种压缩方案(局部压缩);
3.G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换;
4.G1的收集都是STW的,但年轻代和老年代的收集界限比较模糊,采用了混合(mixed)收集的方式。即每次收集既可能只收集年轻代分区(年轻代收集),也可能在收集年轻代的同时,包含部分老年代分区(混合收集),这样即使堆内存很大时,也可以限制收集范围,从而 降低停顿。
- ZGC (1ms) PK C++ 算法:ColoredPointers + LoadBarrier