JVM-G1垃圾收集器原理深入解析

JVM-G1垃圾收集器原理深入解析

首页模拟经营垃圾收集器空闲建造师游戏更新时间:2024-10-28
引言

在针对大型服务器或者是因为gc时间过长而影响用户性能的时候,G1垃圾收集器是一个非常不错的选择,也是我个人认为执行效率最高、对于用户体验有着最大的提高的垃圾收集器,当然前提是JVM服务器内存够大,建议16G或者更大[灵光一闪],否则还是推荐使用CMS ParNew(Old)组合垃圾回收器比较合适。

什么是G1收集器,有什么特点

G1垃圾收集器全称是Garbage-First,意义为进行最有价值的垃圾回收[吐舌](汉语言的优美此刻完美体现)。G1是面向服务器级的垃圾收集器,主要针对多CPU以及大容量内存的机器,具有高吞吐量以及低GC停顿时间。

G1垃圾收集器的堆划分和其他垃圾收集器不大一样,G1将java 堆划分为若干个大小相等的堆内存区域,后面称为region。JVM堆中最多可以存在2048个region,每个region的大小就是堆的内存空间除以region个数,当然可以通过配置 -XX:G1HeapRegionSize 参数对region大小进行手动指定,不过因为G1内部有非常多的堆空间优化机制,所以推荐使用默认配置,不建议修改。

G1堆内存空间示例图

G1收集器堆空间分区情况

G1除了有其他垃圾收集器包含的eden、survivor、old外,还有一个特殊的humongous区,专门用于存储大对象,以下是每个分区功能以及特点:

  1. Eden、Survivor:新生代空间,G1中新生代默认初始空间占比为5%,可以通过配置修改此初始值,不过因为G1内部会在新生代空间不足时,根据内部算法自动增加新生代内存空间,所以不建议修改初始值。JVM在运行过程中,会不断给新生代空间分配内存,最高不超过60%,可以通过 -XX:G1MaxNewSizePercent 参数进行调整。新生代中eden和survior的内存分配为8:1:1
  2. Humongous:G1大对象分配区,在G1中,大对象的判定规则为超过单个region区域内存的50%即为大对象,大对象不需要心如新生代,直接进入humongous区,避免了大对象经历多次gc,影响jvm整体gc性能,也避免了这种短期生存的大对象挤压老年代内存空间,避免full gc的提前发生。如果单个对象大小超过一个region区域内存限制,G1则会给此对象分配多个连续的region空间进行存储。full gc运行时,也会对humongous区域的对象进行gc回收
  3. Old:除了其分布在多个region空间的特点之外,和其他收集器老年代功能以及用法一致
G1垃圾收集过程

G1垃圾收集整体过程和CMS类似核心思想也是降低业务线程停顿时间,让业务线程和gc线程并行工作,提高用户体验,不过G1的具体实现上更为优秀(当然大内存和CPU资源是必不可少)

  1. 初始标记:此阶段和CMS初始标记一致,会标记GC Root根直接关联的对象,此时暂停除GC线程外的所有
  2. 并发标记:此阶段和CMS并发标记一致,会并发标记初始标记对象的关联对象,业务线程同时运行,并记录此时业务线程导致的对象引用更新
  3. 最终标记:此阶段和CMS并发标记一致,会修正并发标记阶段业务线程导致的对象引用更新,此时暂停除GC线程以外的线程
  4. 筛选回收:G1的回收算法使用的是复制算法,筛选回收的意思是G1会根据 其参数设置对region区域进行选择性回收,G1内部会分析每个region的回收价值以及回收所需时长,如果单个region的可回收对象大小不足15%(可配置),G1则不会回收此region区域。同时G1会根据region区域需要的回收时长以及JVM设置的GC停顿时间来合理地进行内存回收。例如用户设置的GC停顿时长为100ms,G1会根据后台维护的优先列表来计算在100ms内能回收的最大region数,回收时间过程的不会进行回收,如果region合计回收时间远小于100ms,G1也不会进行回收,而是会开辟新的region空间存放对象

G1收集器运行示意图

G1优势
  1. 高性能且与支持并行:在多核CPU前提下,充分使用CPU资源,做到并发且并行地进行垃圾收集,极大地减少了 stop the world的时长
  2. 支持分代收集:G1收集器可以直接对整个JVM 堆进行管理,不像CMS、ParNew等收集器只能对老年代或者新生代进行垃圾清理
  3. 空间整合:G1收集器采用的是复制收集算法,效率高于CMS的标记回收算法
  4. 停顿时长可设置:G1根据自带的停顿预测算法,让用户线程的停顿时间尽可能借用JVM设置的停顿时间,极大的提升了用户体验
G1垃圾收集方式
  1. YoungGC: 对G1 Eden区内存回收的回收方式,不过G1并不是在Eden区一满就会触发Young GC,而是会计算当前Eden区如果执行young gc需要执行的时间是否接近 预测停顿时长(通过参数 -XX:MaxGCPauseMills 进行设置),如果接近则会执行young gc,如果远小于预测停顿时长,则会继续分配region给eden空间给新对象存放
  2. MixedGC:此回收方式会对新生代以及部分老年代以及大对象区进行回收,老年区的回收空间大小是根据G1的内部算法,结合jvm设置的预测停顿时间,将老年区价值高的垃圾对象优先进行回收,使用的是复制算法,会将标记的有用对象复制到其他region中,再对需要清除的region进行全量清除,当无剩余region空间作为复制算法的目标空间时,就会触发full gc
  3. FullGC: 此回收方式非常简单粗暴,即使用单线程对内存空间进行标记清理以及压缩处理
G1收集器参数设置
  1. -XX: UseG1GC:G1开启参数
  2. -XX:ParallelGCThreads:并发标记GC线程数
  3. -XX:G1HeapRegionSize:指定region分区大小,必须是2的整数次幂,最大32m,默认算法会将jvm堆空间划分为2048个region
  4. -XX:MaxGCPauseMillis:预测GC最大暂停时长,此参数对于G1收集器非常关键,默认200毫秒,需要根据具体业务进行设置
  5. -XX:G1NewSizePercent:新生代初始内存占比(默认5%,不建议修改)
  6. -XX:G1MaxNewSizePercent:新生代最大空间占比(默认60%,根据实际业务调整)
  7. -XX:TargetSurvivorRatio:survivor触发转移对象至老年代的阈值(默认50%),当survivor分区内存空间超过此阈值,会将年龄相比最大的对象移入老年区,直至survivor空间所用内存低于阈值
  8. -XX:MaxTenuringThreshold:新生代区最大年龄阈值,对象年龄达到此阈值后对象移入老年代
  9. -XX:InitiatingHeapOccupancyPercent:老年代空间占整体堆空间比例超过此阈值时,会触发mixgc,默认为45%
  10. -XX:G1HeapWastePercent:mixgc释放内存空间阈值,当jvm执行mixed gc后,会不断地有未空闲的region块被释放,当释放的region总内存量占堆空间比例达到此阈值后,停止mixed gc,默认5%
  11. -XX:G1MixedGCLiveThresholdPercent:当进行gc时,会计算当前region不可回收对象占region空间比例,如果该比例高于此阈值,则不会回收,默认85%
  12. -XX:G1MixedGCCountTarget:因为G1为了提高用户体验,回收过程中的筛选回收会分多次进行,此参数用于这是筛选回收拆分执行次数,默认8次
G1收集器使用建议

其实所有的垃圾回收器的优化都是大同小异,都是需要防止minor gc的频繁触发以及防止新生代的短期存活对象进入老年代,而G1收集器优化的最重要的点就是 -XX:MaxGCPauseMillis 参数,通过此参数可以设置新生代垃圾回收频率,同时可以基于对业务的评估,设置此参数,防止survivor区对象超过50%而短期存活对象被迫进入老年代的问题

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved