JVM专题十二:JVM 中的收集器二

发布于:2024-07-04 ⋅ 阅读:(19) ⋅ 点赞:(0)

上一篇JVM专题十一:JVM 中的收集器一咱们介绍了垃圾收集器的分类,已经主流的分代垃圾收集器重点看了CMS与三色标记算法,本篇咱们继续来看意G1、ZGC等。

G1收集器

G1(Garbage-First Garbage Collector)是一种服务器端的垃圾收集器,专为大堆内存和低延迟垃圾收集设计。以下是G1收集器的关键特性和工作模式的概述:

G1收集器关键特性

  1. 分代收集:G1将堆内存分为多个大小相等的区域(Region),每个Region可以是Eden、Survivor或Old区。

    • 可以通过-XX:G1HeapRegionSize=n设置Region大小。
  2. 大对象处理:大对象(超过Region大小50%的对象)会被放入专门的Humongous区。

    • 大对象可能横跨多个Region。
  3. 增量回收:G1可以逐步、增量地执行垃圾回收,有助于控制停顿时间。

  4. 并行回收:G1可以利用多核CPU并行回收垃圾,提高回收速度。

  5. 标记-整理算法:老年代回收使用标记-整理算法,避免内存碎片化。

    • 新生代回收使用复制算法。
  6. STW(Stop the World):G1在垃圾回收时仍需STW,但增加了预测机制来控制停顿时间。

  7. 停顿时间预测:用户可以通过-XX:MaxGCPauseMillis指定期望的停顿时间。

G1收集器工作模式

  1. Young GC:当Eden区内存不足时触发,回收新生代Region。

  2. Mixed GC:当老年代空间占比超过-XX:InitiatingHeapOccupancyPercent设定的阈值时触发,回收年轻代和部分老年代Region。

    • 采用复制算法。
  3. 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收集器的优化建议:

  1. 合理设置-XX:MaxGCPauseMillis:这个参数定义了G1试图达到的最大GC停顿时间。如果设置得过高,可能会导致年轻代GC不频繁,从而在触发时有大量对象存活并晋升到老年代。相反,如果设置得过低,可能会导致GC过于频繁,影响整体性能。

  2. 监控年轻代GC后的存活对象:监控每次年轻代GC后存活下来的对象数量,以评估当前的GC策略是否有效。如果存活对象过多,可能需要调整-XX:MaxGCPauseMillis或其他相关参数。

  3. 调整新生代大小:通过-XX:G1NewSizePercent-XX:G1MaxNewSizePercent参数调整新生代的大小,以适应应用的特定需求。确保新生代足够大,可以容纳大部分短暂存活的对象,减少对象晋升到老年代的频率。

  4. 监控Survivor区使用情况:Survivor区溢出是对象晋升到老年代的一个常见原因。如果Survivor区频繁溢出,可能需要增加其大小或调整其他参数。

  5. 使用动态年龄判定规则:G1使用动态年龄判定规则来决定对象何时晋升到老年代。监控这一规则的效果,并根据应用的行为调整-XX:TargetSurvivorRatio-XX:MaxTenuringThreshold参数。

  6. 避免频繁的Mixed GC:频繁的Mixed GC可能会影响性能。通过调整参数,尽量使Mixed GC在必要时才触发,并且每次回收的Region数量能够有效地控制停顿时间。

  7. 监控和优化Full GC:虽然G1旨在减少Full GC的发生,但在某些情况下仍然可能触发。监控Full GC的发生频率,并优化堆空间使用,以减少Full GC的影响。

  8. 使用G1收集器的调优工具:使用JVM提供的工具,如GC日志和JVM监控工具,来分析GC行为并进行调优。

  9. 考虑应用特定行为:不同的应用可能有不同的内存分配模式和GC需求。根据应用的具体行为来调整G1的参数,以达到最优性能。

  10. 测试和评估:在不同的负载和条件下测试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)暂停和四个并发阶段组成:

  1. 标记开始(Mark Start):初始标记GC Roots直接可达的对象。
  2. 重新映射开始(Relocation Start):选择将要清理的内存区域,并建立数据结构以进行对象移动。
  3. 并发标记/重新映射 (M/R):并发遍历对象图,标记所有可达的对象,并更新指向移动对象的引用。
  4. 并发引用处理 (RP):处理软引用、弱引用等特殊引用类型。
  5. 并发转移准备 (EC):确定哪些内存区域将被清理,并准备数据结构。
  6. 并发转移 (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垃圾收集器的发展提供了新的方向。

专题汇总

JVM专题一:深入分析Java工作机制

JVM专题二:Java如何进行编译的

JVM专题三:Java代码如何运行

JVM专题四:JVM的类加载机制

JVM专题五:类加载器与双亲委派机制

JVM专题六:JVM的内存模型

JVM专题七:JVM垃圾回收机制

JVM专题八:JVM如何判断可回收对象

JVM专题九:JVM分代知识点梳理

JVM专题十:JVM中的垃圾回收机制

JVM专题十一:JVM 中的收集器一

JVM专题十二:JVM 中的收集器二

JVM专题十三:总结与整理(面试常用)