垃圾回收器(二):G1

堆空间

  • 自由分区(Free Heap Region,FHR)
  • 新生代分区(Young Hreap Region,YHR)
    • E 是 eden region
    • S 是 survivor region
  • 老年代分区(Old Heap Region,OHR)
    • 如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象
    • 大对象分区(Humongous Heap Region,HHR)
      • 短期存在的巨型对象
      • G1 只决定它们是否生存,回收他们占用的空间,从不会移动它们
      • 可以跨越多个连续regions。直接分配到老年代,防止反复拷贝移动
      • 在global concurrent marking阶段的cleanup 和 full GC阶段回收
      • 在分配H-obj之前先检查是否超过 initiating heap occupancy percent和the marking threshold, 如果超过的话,就启动global concurrent marking,为的是提早回收,防止 evacuation failures 和 full GC
      • Young-Only 阶段,humongous regions 可能会被回收
      • Space-Reclamation,humongous regions 可能会被回收
      • 为了减少连续H-objs分配对GC的影响,需要把大对象变为普通的对象,建议增大Region size。
      • 一个Region的大小可以通过参数-XX:G1HeapRegionSize设定,取值范围从1M到32M,且是2的指数

GC

  • G1提供了两种GC模式,Young GC和Mixed GC,两种都是完全Stop The World的
  • Young GC:选定所有年轻代里的Region。
  • Mixed GC:选定所有年轻代里的Region,外加根据global concurrent marking统计得出收集收益高的若干老年代Region。在用户指定的开销目标范围内尽可能选择收益高的老年代Region。Mixed GC不是full GC,它只能回收部分老年代的Region
  • 如果mixed GC实在无法跟上程序分配内存的速度,导致老年代填满无法继续进行Mixed GC,就会使用serial old GC(full GC)来收集整个GC heap。G1是不提供full GC的。如果堆是足够大的,Mixed gc 没有回收足够的 old region,或者 concurrent mark 没法及时完成,都可能会导致 full gc。
  • 在几次gc后,old gen 的对象占有比超过了 InitiatingHeapOccupancyPercent,gc就会进入并发标记准备(concurrent mark)。Mixed gc 依赖 concurrent mark
  • G1默认当分区内存占用阈值达到总内存的45%,会发生Mixed gc(混和GC)

GC 流程

YGC流程:

  1. 挂起所有用户线程,应用程序暂时不能向外提供响应(STW)
  2. 计算需要收集的区间(CSet),YGC期间,仅回收Y区,所以所有的Y区就是CSet
  3. 进行根处理,包含JVM根和Java根。为了扫描全堆,这里只需要把RSet记录的对象加入根即可
  4. JIT代码扫描等,根据栈中的对象进行递归遍历复制对象
  5. 因为对象已经有挪动,更新JIT代码中指针存储的对象地址
  6. 引用处理,一些软、弱、虚、析构(FinalReference)引用等的处理
  7. 字符串去重等处理
  8. 清理卡表,也就是把全局卡表中已经处理过的分区的卡表清空
  9. 进行Redirty操作,也就是重构RSet。释放CSet区
  10. 尝试回收大对象,如果某个大对象所在的分区没有RSet引用,说明这个大对象已经死亡,可以直接回收
  11. 尝试扩展内存,参数有GCTimeRatio和GExpandByPercentOfAvailable来决定是否需要扩展,前者在G1中默认值是9,代表的意思是GC占用的时间必须小于1/(1+9),也就是10%,这个值在之前的垃圾收集器默认值是99。如果吞吐量不达标,就会尝试扩展内存,大小由GExpandByPercentOfAvailable决定,默认20,也就是未提交内存的20%
  12. 如果满足条件的,触发并发标记周期;判断方式是YGC之后,老年代内存占总内存超过一定阈值(参数-XX:InitiatingHeapOccupancyPercent决定,默认45%)触发。

混合回收:

  • 根扫描,初始标记:并发标记周期之前一定有一次YGC,所以初始标记会把这次YGC的存活对象也加入根,还有其他根对象,如:栈对象、全局静态对象、JNI对象等等
  • 并发标记(concurrent-mark-start~end之间):因为存活对象会比较多,所以这块耗时会比较久,CMS、G1等的这部肯定都是"并发执行的",要不过长的STW时间,会一定程度上的导致服务运行。并且并发标记过程是涉及所有区的,所有老年代区的对象都参与标记。在标记的过程中也会计算每个区的存活对象数目和字节数。
  • 再标记:再标记过程是有STW。再标记的目的是处理哪些在并发标记过程中有引用关系变更的对象,见"2.c并发标记的难点"。
  • 清理:清理阶段会统计存活对象,并且按照结果对区维度进行排序,以便后续mixed-gc的CSet的选择。同时和会重置RSet,因为老年代的标记已经完成了,这个时候需要删除原来RSet里面保存的引用关系。
相关推荐
2301_7820404511 分钟前
CSS Flex布局中如何实现导航栏与Logo的左右分布_利用justify-content- space-between
jvm·数据库·python
沐浴露z3 小时前
面试官:静态变量与非静态成员变量的区别?别再死记硬背了!
java·jvm
Chase_______7 小时前
Java 基础语言 ① —— Java 运行机制与开发环境:从 javac 到 JVM 全流程解析
java·jvm·python
xqqxqxxq7 小时前
多线程、进程与JVM 技术笔记
jvm·笔记
cui_ruicheng7 小时前
Linux线程(二):pthread 线程库与线程控制
java·开发语言·jvm
不知名的老吴8 小时前
C++20的jthread使用基础及实例分析
jvm
Devin~Y8 小时前
大厂Java面试实战:Spring Boot/Cloud、Redis/Kafka、JVM调优与Spring AI RAG(内容社区UGC+AIGC客服场景)
java·jvm·spring boot·redis·spring cloud·kafka·mybatis
AI人工智能+电脑小能手8 小时前
【大白话说Java面试题 第42题】【JVM篇】第2题:JVM内存模型有哪些组成部分?
java·开发语言·jvm·面试
青柠代码录8 小时前
【JVM】面试题-对象的内存布局
jvm
AI人工智能+电脑小能手8 小时前
【大白话说Java面试题 第43题】【JVM篇】第3题:GC分为哪两种?Young GC 和 Full GC有什么区别?
java·开发语言·jvm·后端·面试