S++

千线一眼

导航

JVM-垃圾回收(3)

垃圾回收器补充——G1(Garbage First)

G1垃圾回收器在2012年JDK 7u4中得到官方支持
而在2017年的JDK9更是将其设定为默认的垃圾回收器

G1的特点很多:

  • 同时注重吞吐量(Throughput)低延迟(Low Latency),默认的暂停目标是200ms
  • 适用超大的堆内存,会将堆划分为多个大小相等的区域Region
  • 整体采用标记-整理算法,而两个区域Region之间采用复制算法

相关的JVM参数:

-XX:UseG1GC

-XX:G1HeapRegionSize=size

-XX:MaxGCPauseMillis=time

解释:

  • 启动G1
  • 设置区域的大小
  • 设置暂停目标

G1的垃圾回收过程

1. G1的堆结构和堆分配

G1的堆结构分为许多固定大小的区域,这些区域被映射到伊甸园、幸存区和老年代的逻辑表示中。

分配详情

就以上面的图片为例,绿色的是伊甸区,黄色的是幸存区,蓝色的是老年代
值得注意的是,这些区域不需要像之前的的垃圾收集器那样相连。
此外,还有第四种类型的区域被称为Humongous区域。这些区域被设计用来容纳大小为标准区域50%或更大的对象。


2. G1中的Young GC

存活的对象被疏散(即复制或移动)到一个或多个幸存者区域。如果达到衰老阈值,一些对象将推广到老年代区域。
G1中的Young GC同样会触发STW

Minor GC过程

Minor GC结束

最近进入幸存区域的对象用深绿色表示,最近进入老年区域的用深蓝色表示。

总结:

  • 堆是分割成区域的单个内存空间。
  • 年轻代内存由一组不连续的区域组成。这使得在需要时可以很容易地调整大小。
  • 年轻代垃圾收集或Young GC是STW事件。所有应用程序线程都将为此操作停止。
  • Young GC使用多个线程并行完成。
  • 活动对象被复制到新的幸存区或老年代区域。

3. G1中的Old GC阶段

阶段 描述
(1)初始标记 (STW事件) 这是一个STW事件。对于G1,初始标记承载在Young GC上。标记幸存者区域(根区域),可能老年代中有对象引用这些区域。
(2)根区域扫描 扫描幸存者区域以查找老年代中的引用。这是在应用程序继续运行时发生的。这个阶段必须在Young GC发生之前完成。
(3)并行标记 在整个堆上查找活跃对象。这发生在应用程序运行时。此阶段可被年轻代垃圾收集中断。
(4)再标记 (STW事件) 完成堆中活动对象的标记。使用一种称为snapshot-at-the-beginning(SATB)的算法,它比CMS收集器中使用的算法快得多。
(5)清除 (STW事件和并发) 对活动对象和完全自由的区域执行计算(STW);清除(STW);重置空区域并将它们返回到空闲列表(并发)
(*)复制 (STW事件) 疏散或者复制存活的对象到新的未使用的区域

活动对象的初始标记由年轻代垃圾收集承载。在日志中,这被记录为GC pause (young)(inital-mark)
如果发现空区域(如“X”所示),则会在Remark阶段立即删除它们。

空区域被移除并回收,现在要计算所有区域活跃信息。
G1选择“活跃信息”最低的区域,即收集起来速度最快的区域。然后,这些区域与Young GC同时被收集。这在日志中表示为[GC pause (mixed)]。所以年轻一代和年老一代同时被收集。

所选区域已被收集并压缩为图中所示的深蓝区域和深绿色区域。

总结:

  • 并发标记阶段
    • 活跃信息是在应用程序运行时并发计算的。
    • 这个活跃信息确定了在疏散暂停期间哪些区域最好回收。
    • 没有像CMS那样的sweeping清扫阶段。
  • 再标记阶段
    • 使用Snapshot-the-Beginning(SATB)算法,该算法比CMS使用的要快得多。
    • 完全空的区域被回收。
  • 复制/清理阶段
    • 年轻代和老年代同时被回收。
    • 老年代区域是根据它们的活跃度来选择的。



觉得表达不够准确,可以点这里哦



posted on 2022-05-06 21:45  S++  阅读(64)  评论(0)    收藏  举报