java Garbage
1、G1(Garbage-First)收集器
1、serial、parallel、cms 内存布局
较老的垃圾收集器(串行、并行、CMS)都将堆结构分为三个部分:年轻代、老年代和固定内存大小的永久代。
1、cms流程 (老年代 92 - 标记-清理)
- 初始标记
- 动作:标记 GC Roots 直接关联 的老年代对象。
- 特点:需要 STW,但速度极快,因为关联对象很少。
- 并发标记
- 动作:从初始标记的对象开始,进行 GC Roots Tracing,遍历整个对象图,标记所有存活对象。
- 特点:与用户线程并发执行,无需 STW。这是 CMS 实现低延迟的关键,但也是最耗时的阶段。
- 重新标记
- 动作:修正 并发标记 阶段因用户程序继续运行而导致标记产生变动的对象。
- 特点:需要 STW。为了提升效率,CMS 使用了一些技术(如 增量更新)来减少需要重新扫描的范围。此阶段的停顿时间通常比初始标记长,但远短于并发标记。
- 并发清除
- 动作:清除未被标记的死亡对象,回收内存空间。
- 特点:与用户线程并发执行,无需 STW。
浮动垃圾、内存碎片化(-XX:+UseCMSCompactAtFullCollection)
2、G1 收集器详解
堆被划分为一组等大小的堆区域,每个区域都是一个连续的虚拟内存范围。某些区域集被分配了与较老收集器中相同的角色(伊甸园、幸存者、老年代),但它们没有固定的大小。这为内存使用提供了更大的灵活性。
1、年轻代回收
Young GC(年轻代回收)
- 触发时机:当 Eden Region 被占满时触发。
- 过程:
- STW:停止所有应用线程。
- 创建回收集:将所有的 Eden Region 和一部分 Survivor Region 加入 CSet。
- 根扫描与 RSet 扫描:从 GC Roots 和 CSet 中 Region 的 RSet 开始,标记存活对象。
- 对象拷贝:将 CSet 中所有存活的对象拷贝到新的、空的 Region 中(这些新的 Region 就成为 Survivor Region),或者直接晋升到 Old Region(如果对象年龄超过阈值或 Survivor 空间不足)。
- 清空 Region:整个 CSet 中的 Region 现在已完全清空,可以重新用于分配。
- 特点:这是一个 STW、并行、复制式的回收过程。
2、老年代回收
阶段 | 描述 |
---|---|
(1) 初始标记*(Stop the World Event)* | 这是一个停止世界的活动。在 G1 中,它依赖于一个正常的年轻代垃圾回收器。标记可能包含指向旧代对象的幸存区域(根区域)。 |
(2) 根区域扫描 | 扫描幸存区域中的旧生代引用。这发生在应用程序运行期间。此阶段必须在年轻代垃圾回收发生之前完成。 |
(3) 并发标记 | 在整个堆中查找存活对象。这发生在应用程序运行期间。此阶段可以被年轻代垃圾回收中断。 |
(4) Remark (Stop the World Event) | 完成堆中活动对象的标记。使用了一种称为“开始时快照”(SATB)的算法,比 CMS 收集器中使用的算法快得多。 |
(5) Cleanup (Stop the World Event and Concurrent) | 对活动对象和完全空闲区域执行记账。(停止世界);清除已记录集合。(停止世界);重置空区域并将它们返回到空闲列表。(并发) |
(*) Copying (Stop the World Event) | 这些是停止世界暂停以疏散或复制活动对象到新未使用区域的情况。这可以通过记录为 [GC pause (young)] 的年轻代区域完成。或者,也可以通过记录为 [GC Pause (mixed)] 的年轻和旧代区域完成 |
3、G1配置参数
选项和默认值 | 描述 |
---|---|
-XX:+UseG1GC | 使用垃圾优先(G1)收集器 |
-XX:MaxGCPauseMillis=n | 设置最大 GC 暂停时间的目标。这是一个软目标,JVM 将尽力实现它。 |
-XX:InitiatingHeapOccupancyPercent=n | 启动并发 GC 周期的堆占用百分比。它用于基于整个堆占用情况触发并发 GC 周期的 GC,而不仅仅是某一代(例如,G1)。0 表示“执行常量 GC 周期”。默认值为 45。 |
-XX:NewRatio=n | 新/旧代大小比例。默认值为 2。 |
-XX:SurvivorRatio=n | Eden 和 Survivor 空间大小的比例。默认值为 8。 |
-XX:MaxTenuringThreshold=n | 十岁阈值的最大值。默认值为 15。 |
-XX:ParallelGCThreads=n | 设置垃圾收集器并行阶段使用的线程数。默认值因 JVM 运行的平台而异。 |
-XX:ConcGCThreads=n | 并发垃圾收集器将使用的线程数。默认值因 JVM 运行的平台而异。 |
-XX:G1ReservePercent=n | 设置保留的堆空间量,作为虚假的上限以减少晋升失败的可能性。默认值为 10。 |
-XX:G1HeapRegionSize=n | 在 G1 中,Java 堆被细分为均匀大小的区域。此参数设置单个子区域的尺寸。此参数的默认值基于堆大小进行人体工程学确定。最小值为 1MB,最大值为 32MB。 |
TODO
2、ZGC(Z Garbage Collector)
ZGC是一个可扩展的低延迟垃圾收集器。ZGC 以并发方式执行所有昂贵的操作,不会停止应用程序线程超过一毫秒。它适用于需要低延迟的应用程序。暂停时间与使用的堆大小无关。ZGC 适用于从几百兆字节到 16TB 的堆大小。
- Concurrent 并发
- Region-based 基于区域的
- Compacting 压缩
- NUMA-aware NUMA 感知
- Using colored pointers 使用彩色指针
- Using load barriers 使用加载屏障
- Using store barriers (in the generational mode) 使用存储屏障(分层)
3、Shenandoah收集器
Shenandoah 是一种低暂停时间的垃圾回收器,通过在运行中的 Java 程序并发执行更多的垃圾回收工作来减少 GC 暂停时间。Shenandoah 大部分 GC 工作都是并发的,包括并发压缩,这意味着其暂停时间不再与堆的大小成正比。回收 200 GB 的堆或 2 GB 的堆应该具有类似的低暂停行为。
GC(3) Pause Init Mark 0.771ms
GC(3) Concurrent marking 76480M->77212M(102400M) 633.213ms
GC(3) Pause Final Mark 1.821ms
GC(3) Concurrent cleanup 77224M->66592M(102400M) 3.112ms
GC(3) Concurrent evacuation 66592M->75640M(102400M) 405.312ms
GC(3) Pause Init Update Refs 0.084ms
GC(3) Concurrent update references 75700M->76424M(102400M) 354.341ms
GC(3) Pause Final Update Refs 0.409ms
GC(3) Concurrent cleanup 76244M->56620M(102400M) 12.242ms
4、Epsilon收集器
无回收清理 ,仅适用性能测试
参考
https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html
https://wiki.openjdk.org/display/zgc/Main
https://wiki.openjdk.org/display/shenandoah
https://developer.aliyun.com/article/726110