上一篇JVM专题十一:JVM 中的收集器一咱们介绍了垃圾收集器的分类,已经主流的分代垃圾收集器重点看了CMS与三色标记算法,本篇咱们继续来看意G1、ZGC等。
G1收集器
G1(Garbage-First Garbage Collector)是一种服务器端的垃圾收集器,专为大堆内存和低延迟垃圾收集设计。以下是G1收集器的关键特性和工作模式的概述:
G1收集器关键特性
-
分代收集:G1将堆内存分为多个大小相等的区域(Region),每个Region可以是Eden、Survivor或Old区。
- 可以通过
-XX:G1HeapRegionSize=n
设置Region大小。
- 可以通过
-
大对象处理:大对象(超过Region大小50%的对象)会被放入专门的Humongous区。
- 大对象可能横跨多个Region。
-
增量回收:G1可以逐步、增量地执行垃圾回收,有助于控制停顿时间。
-
并行回收:G1可以利用多核CPU并行回收垃圾,提高回收速度。
-
标记-整理算法:老年代回收使用标记-整理算法,避免内存碎片化。
- 新生代回收使用复制算法。
-
STW(Stop the World):G1在垃圾回收时仍需STW,但增加了预测机制来控制停顿时间。
-
停顿时间预测:用户可以通过
-XX:MaxGCPauseMillis
指定期望的停顿时间。
G1收集器工作模式
-
Young GC:当Eden区内存不足时触发,回收新生代Region。
-
Mixed GC:当老年代空间占比超过
-XX:InitiatingHeapOccupancyPercent
设定的阈值时触发,回收年轻代和部分老年代Region。- 采用复制算法。
-
Full GC:当老年代空间不足且
-XX:G1HeapWastePercent
设定过低时可能触发,进行整个堆的回收。
G1收集器参数设置
G1收集器参数设置
-XX:+UseG1GC:使用G1收集器
-XX:ParallelGCThreads:指定GC工作的线程数量
-XX:G1HeapRegionSize:指定分区大小(1MB~32MB,且必须是2的N次幂),默认将整堆划分为2048个分区
-XX:MaxGCPauseMillis:目标暂停时间(默认200ms)
-XX:G1NewSizePercent:新生代内存初始空间(默认整堆5%,值配置整数,默认就是百分比)
-XX:G1MaxNewSizePercent:新生代内存最大空间
-XX:TargetSurvivorRatio:Survivor区的填充容量(默认50%),Survivor区域里的一批对象(年龄1+年龄2+年龄n的多个年龄对象)总和超过了Survivor区域的50%,此时就会把年龄n(含)以上的对象都放入老年代
-XX:MaxTenuringThreshold:最大年龄阈值(默认15)
-XX:InitiatingHeapOccupancyPercent:老年代占用空间达到整堆内存阈值(默认45%),则执行新生代和老年代的混合收集(MixedGC),比如我们之前说的堆默认有2048个region,如果有接近1000个region都是老年代的region,则可能就要触发MixedGC了
-XX:G1MixedGCLiveThresholdPercent(默认85%) region中的存活对象低于这个值时才会回收该region,如果超过这个值,存活对象过多,回收的的意义不大。
-XX:G1MixedGCCountTarget:在一次回收过程中指定做几次筛选回收(默认8次),在最后一个筛选回收阶段可以回收一会,然后暂停回收,恢复系统运行,一会再开始回收,这样可以让系统不至于单次停顿时间过长。
-XX:G1HeapWastePercent(默认5%): gc过程中空出来的region是否充足阈值,在混合回收的时候,对Region回收都是基于复制算法进行的,都是把要回收的Region里的存活对象放入其他Region,然后这个Region中的垃圾对象全部清理掉,这样的话在回收过程就会不断空出来新的Region,一旦空闲出来的Region数量达到了堆内存的5%,此时就会立即停止混合回收,意味着本次混合回收就结束了。
G1收集器优化建议
G1垃圾收集器的优化主要集中于平衡GC的频率和停顿时间,以及管理新生代和老年代之间的对象晋升。以下是一些针对G1收集器的优化建议:
-
合理设置
-XX:MaxGCPauseMillis
:这个参数定义了G1试图达到的最大GC停顿时间。如果设置得过高,可能会导致年轻代GC不频繁,从而在触发时有大量对象存活并晋升到老年代。相反,如果设置得过低,可能会导致GC过于频繁,影响整体性能。 -
监控年轻代GC后的存活对象:监控每次年轻代GC后存活下来的对象数量,以评估当前的GC策略是否有效。如果存活对象过多,可能需要调整
-XX:MaxGCPauseMillis
或其他相关参数。 -
调整新生代大小:通过
-XX:G1NewSizePercent
和-XX:G1MaxNewSizePercent
参数调整新生代的大小,以适应应用的特定需求。确保新生代足够大,可以容纳大部分短暂存活的对象,减少对象晋升到老年代的频率。 -
监控Survivor区使用情况:Survivor区溢出是对象晋升到老年代的一个常见原因。如果Survivor区频繁溢出,可能需要增加其大小或调整其他参数。
-
使用动态年龄判定规则:G1使用动态年龄判定规则来决定对象何时晋升到老年代。监控这一规则的效果,并根据应用的行为调整
-XX:TargetSurvivorRatio
和-XX:MaxTenuringThreshold
参数。 -
避免频繁的Mixed GC:频繁的Mixed GC可能会影响性能。通过调整参数,尽量使Mixed GC在必要时才触发,并且每次回收的Region数量能够有效地控制停顿时间。
-
监控和优化Full GC:虽然G1旨在减少Full GC的发生,但在某些情况下仍然可能触发。监控Full GC的发生频率,并优化堆空间使用,以减少Full GC的影响。
-
使用G1收集器的调优工具:使用JVM提供的工具,如GC日志和JVM监控工具,来分析GC行为并进行调优。
-
考虑应用特定行为:不同的应用可能有不同的内存分配模式和GC需求。根据应用的具体行为来调整G1的参数,以达到最优性能。
-
测试和评估:在不同的负载和条件下测试G1的参数设置,评估其对性能的影响,并根据测试结果进行调整。
通过细致地调整和监控G1收集器的参数,可以优化垃圾收集的性能,减少GC引起的停顿时间,提高应用的响应速度和吞吐量。
G1收集器适用场景
- 大堆内存应用(8GB以上)。
- 对象分配和晋升速度变化大。
- 需要低延迟和可预测停顿时间的垃圾收集。
G1收集器通过其创新的Region划分和垃圾收集策略,为现代Java应用提供了一种有效的垃圾收集解决方案,尤其适用于大堆内存和对延迟敏感的应用场景。通过合理的参数设置和监控,G1可以显著提高应用的性能和响应性。
ZGC收集器
ZGC(The Z Garbage Collector)是Java虚拟机(JVM)在JDK 11中引入的一种实验性质的低延迟垃圾收集器,专为大内存和低延迟服务设计。以下是对ZGC收集器特性和工作过程的整理:
ZGC关键特性
- 低延迟目标:最大GC停顿时间不超过10ms。
- 大堆支持:设计用于支持TB级别的内存容量,当前支持8MB到4TB,未来可支持16TB。
- 与堆大小无关的停顿时间:停顿时间不随堆大小或活跃对象大小的增加而增长。
- 指针染色(Colored Pointer):在对象指针中嵌入额外的位来存储对象的状态信息,如是否被移动或存活状态。
- 读屏障(Load Barrier):在对象访问时插入的特殊检查,用于确保访问的正确性,并处理对象移动后的指针更新。
内存布局
- 采用基于Region的内存布局,但与G1不同,ZGC的Region不分代。
- 64位虚拟地址空间划分为多个子空间,包括Java堆、M0地址空间、M1地址空间和Remapped空间。
工作过程
ZGC周期由三个STW(Stop-The-World)暂停和四个并发阶段组成:
- 标记开始(Mark Start):初始标记GC Roots直接可达的对象。
- 重新映射开始(Relocation Start):选择将要清理的内存区域,并建立数据结构以进行对象移动。
- 并发标记/重新映射 (M/R):并发遍历对象图,标记所有可达的对象,并更新指向移动对象的引用。
- 并发引用处理 (RP):处理软引用、弱引用等特殊引用类型。
- 并发转移准备 (EC):确定哪些内存区域将被清理,并准备数据结构。
- 并发转移 (RE):将存活的对象从旧位置移动到新位置,应用程序可继续运行。
优势
- 利用指针染色和读屏障技术,实现几乎整个垃圾收集过程的并发执行,显著降低停顿时间。
- 支持大容量内存,适用于未来大规模内存需求的应用。
局限性
- 由于采用“空间换时间”的策略,可能会占用更多的地址空间。
- 目前仅支持64位系统,不支持32位系统和压缩指针。
参数设置
类别 | 配置选项 | 说明 |
---|---|---|
通用GC选项 | -XX:MinHeapSize 或 -Xms | 设置JVM堆的最小大小。 |
-XX:InitialHeapSize | 设置JVM堆的初始大小。 | |
-XX:MaxHeapSize 或 -Xmx | 设置JVM堆的最大大小。 | |
-XX:SoftMaxHeapSize | 设置堆大小的软限制,达到此值可能会触发GC。 | |
-XX:ConcGCThreads | 设置并发垃圾收集的线程数量。 | |
-XX:ParallelGCThreads | 设置并行垃圾收集的线程数量。 | |
-XX:UseLargePages | 启用大页内存支持,提高内存分配效率。 | |
ZGC特定选项 | -XX:+UnlockExperimentalVMOptions | 解锁实验性VM选项。 |
-XX:+UseZGC | 启用Z Garbage Collector。 | |
-XX:ZAllocationSpikeTolerance | 设置分配峰值的容忍度。 | |
-XX:ZCollectionInterval | 设置ZGC的垃圾收集间隔。 | |
-XX:ZFragmentationLimit | 设置ZGC堆碎片的容忍度。 | |
-XX:ZMarkStackSpaceLimit | 设置ZGC标记阶段堆栈空间的限制。 | |
-XX:ZUncommit | 控制ZGC是否取消提交未使用的内存区域。 | |
-XX:ZUncommitDelay | 设置ZGC取消提交内存的延迟时间。 | |
ZGC诊断选项 | -XX:+UnlockDiagnosticVMOptions | 解锁诊断VM选项。 |
-XX:zStatisticsInterval | 设置ZGC统计信息输出的间隔。 | |
-XX:ZVerifyForwarding | 启用ZGC转发指针的验证。 | |
-XX:ZVerifyMarking | 启用ZGC标记阶段的验证。 | |
-XX:ZVerifyobjects | 启用ZGC对象的验证。 | |
-XX:ZVerifyRoots | 启用ZGC根对象的验证。 | |
-XX:ZVerifyViews | 启用ZGC视图的验证。 | |
-xx:zProactive | 启用ZGC的主动垃圾收集策略。 | |
其他选项 | -XX:UseNUMA | 启用对非统一内存访问(NUMA)架构的支持。 |
-XX:UseTransparentHugePages | 启用透明大页内存支持。 | |
-XX:SoftRefLRUPolicyMSPerMB | 设置软引用的LRU策略,与每MB内存相关的时间。 | |
堆分配选项 | -XX:AllocateHeapAt | 控制JVM堆分配的内存地址。 |
请注意,某些配置选项可能需要根据具体的JVM实现和版本进行调整。在使用这些选项时应参考官方文档,并在生产环境中进行充分测试。
触发机制
- 支持定时触发、预热触发、分配速率触发和主动触发。
小结
ZGC通过其创新的垃圾收集策略和技术,实现了在大堆内存上的低延迟垃圾收集,特别适用于对延迟敏感的大规模应用。随着JDK版本的更新,ZGC有望得到进一步的优化和性能提升。尽管存在一些局限性,ZGC的设计理念和实现技术为Java垃圾收集器的发展提供了新的方向。