简介
G1(Garbage First)垃圾收集器是 Java 7 Update 4 及以上版本引入的一款面向服务端应用的垃圾收集器,旨在满足大内存、多处理器系统的需求,在 JDK 9 中被指定为默认的垃圾收集器。
设计目标
高吞吐量与低停顿:G1 垃圾收集器的主要目标是在具备高吞吐量的同时,尽可能地减少垃圾收集时的停顿时间。它能够在满足应用程序低延迟要求的同时,保持较高的性能。 可预测的停顿:G1 允许用户通过 -XX:MaxGCPauseMillis 参数来设置最大垃圾收集停顿时间,使得应用程序的响应时间更加可预测。
内存布局
分区(Region):G1 不再像传统的垃圾收集器那样将堆内存划分为固定大小的新生代、老年代和永久代(Java 8 之后为元空间)。而是将整个堆内存划分为多个大小相等的独立区域(Region),每个 Region 的大小可以通过 -XX:G1HeapRegionSize 参数指定,范围为 1MB 到 32MB,且必须是 2 的幂次方。 特殊区域:这些 Region 被标记为 Eden、Survivor、Old 或 Humongous(大对象)。其中,Humongous 区域专门用于存储大对象,如果对象大小超过单个 Region 大小的一半,就会被分配到 Humongous 区域。如果一个 Humongous 区域放不下一个大对象,G1 会连续使用多个 Humongous 区域来存储。
垃圾收集过程
G1 垃圾收集器的垃圾收集过程主要分为以下几个阶段:
-
初始标记(Initial Mark) Concurrent Scan Root Regions 作用:标记所有的根对象直接引用的对象。 特点:这个阶段需要暂停所有的应用线程(Stop The World,STW),但停顿时间非常短暂。
-
并发标记(Concurrent Marking) Concurrent Mark From Roots 作用:从初始标记阶段标记的根对象开始,并发地遍历整个堆,标记所有存活的对象。 特点:这个阶段可以与应用线程并发执行,不会造成长时间的停顿。
-
最终标记(Final Marking) 作用:处理并发标记阶段遗留下来的少量未标记对象。 特点:需要暂停所有的应用线程,停顿时间比初始标记阶段稍长,但也比较短暂。
-
筛选回收(Live Data Counting and Evacuation) 作用:根据用户设置的最大停顿时间,对各个 Region 的回收价值和成本进行排序,选择一部分 Region 进行回收。 特点:这个阶段需要暂停所有的应用线程,通过复制算法将存活的对象复制到其他空闲的 Region 中,然后清理掉这些被回收的 Region。
优势
-
并行与并发:G1 可以充分利用多核处理器的优势,并行执行垃圾收集操作,同时在某些阶段可以与应用线程并发执行,减少了停顿时间。 分代收集:虽然 G1 不再严格区分新生代和老年代,但它仍然保留了分代的概念,不同类型的对象可以分配到不同的 Region 中,提高了垃圾收集的效率。
-
空间整合:G1 使用复制算法进行垃圾回收,在回收过程中会将存活的对象复制到其他空闲的 Region 中,从而避免了内存碎片的产生。 可预测的停顿时间:通过 -XX:MaxGCPauseMillis 参数,用户可以控制垃圾收集的最大停顿时间,使得应用程序的响应时间更加稳定。
劣势
内存占用:G1 垃圾收集器需要维护一些额外的数据结构来管理 Region 和标记对象,因此会占用一定的内存空间。 算法复杂度:G1 的垃圾收集算法相对复杂,需要更多的计算资源来执行垃圾收集操作,在某些情况下可能会影响应用程序的性能。
[50.271s][info ][gc,marking ] GC(36) Concurrent Scan Root Regions 3.015ms
[50.271s][info ][gc,marking ] GC(36) Concurrent Mark
[50.271s][info ][gc,marking ] GC(36) Concurrent Mark From Roots
[50.271s][info ][gc,task ] GC(36) Using 4 workers of 4 for marking
[50.295s][info ][gc,marking ] GC(36) Concurrent Mark From Roots 24.165ms
[50.295s][info ][gc,marking ] GC(36) Concurrent Preclean
[50.295s][info ][gc,marking ] GC(36) Concurrent Preclean 0.142ms
[50.295s][info ][gc,start ] GC(36) Pause Remark
[50.303s][info ][gc ] GC(36) Pause Remark 116M->116M(256M) 7.501ms
[50.303s][info ][gc,cpu ] GC(36) User=0.02s Sys=0.00s Real=0.01s
[50.303s][info ][gc,marking ] GC(36) Concurrent Mark 32.251ms
[50.303s][info ][gc,marking ] GC(36) Concurrent Rebuild Remembered Sets and Scrub Regions
[50.324s][info ][gc,marking ] GC(36) Concurrent Rebuild Remembered Sets and Scrub Regions 20.854ms
[50.324s][info ][gc,start ] GC(36) Pause Cleanup
[50.324s][info ][gc ] GC(36) Pause Cleanup 118M->118M(256M) 0.141ms
[50.324s][info ][gc,cpu ] GC(36) User=0.00s Sys=0.00s Real=0.00s
[50.324s][info ][gc,marking ] GC(36) Concurrent Clear Claimed Marks
[50.324s][info ][gc,marking ] GC(36) Concurrent Clear Claimed Marks 0.080ms
[50.324s][info ][gc,marking ] GC(36) Concurrent Cleanup for Next Mark
[50.325s][info ][gc,marking ] GC(36) Concurrent Cleanup for Next Mark 0.239ms
[50.325s][info ][gc ] GC(36) Concurrent Mark Cycle 56.876ms