G1垃圾回收器介绍和线上实践

张开发
2026/4/15 4:25:16 15 分钟阅读

分享文章

G1垃圾回收器介绍和线上实践
一、前言Java语言相较于C++等语言,一个显著的特点是垃圾回收机制,允许程序员在编写程序时无需考虑内存管理,统一由底层的垃圾回收机器进行垃圾回收。但是垃圾回收器在回收垃圾时,会对应用线程造成停顿,影响应用的性能。在Java应用调优中,核心的两个指标为:响应时间和吞吐量。1.1 响应时间响应时间指的是应用对请求的响应时间,如:一个桌面应用对时间的响应时间网站返回一个页面的时间数据库查询结果返回时间对于专注于最小响应时间的应用,长时间停顿是无法接受的。1.2 吞吐量吞吐量专注于应用在一段时间的的最大工作量。如:给定时间内完成的事物数每小时批处理程序能够完成的任务每小时数据库可以完成的查询操作数较长停顿时间在此情况下是可以接受的。比起低响应时间,吞吐量优先应用更看重一段时间内的表现。1.3 总结基于两个指标,可得出评估一个垃圾回收器在实际业务中关键的是:单次最大停掉时间和周期内的停顿次数。注:本文介绍的G1主要是基于JDK8进行分析,在后续的JDK版本中,有较多优化,比如JDK10 退化后的Full GC支持多线程等。二、G1垃圾回收器Garbage-First(G1)收集器时一款服务端垃圾收集器,主要针对多处理器、大内存环境设计。在尽可能满足GC停顿时间目标的同时获取更高的吞吐量。在JDK7u4版本开始支持;2.1 基本介绍2.1.1 设计目标像CMS那样做到并发GC,提高GC并行和并发表现没有内存碎片问题,内存整理过程不需要延长GC时间,不需要虚拟机停顿STW可预测的GC停顿时间更高的吞吐量在不增加堆内存大小下更好地利用堆内存G1的远期目标时替代CMS+ParNew(自适应的、分代的、停顿-复制、标记-清理并发垃圾回收器)组合。2.1.2 优点与CMS相比,G1优点包括:G1是内存整理虚拟机,G1通过对堆内存划分区域(region),分区管理,避免使用细粒度空闲列表来实现高效内存整理;G1提供比CMS更加可预测的GC停顿时间,并允许用户设定停顿时间目标。2.1.3 推荐应用场景G1的设计初衷是为用户提供大内存、低GC停顿时间的应用解决方案。如果应用正在使用CMS或ParallelOld且面临以下问题,推荐将应用迁移至G1FullGC发生频繁或总时间过长对象分配率或对象升级至老年代的比例波动较大较长的垃圾收集或内存整理停顿(大于0.5至1秒)注意:如果应用没有上述问题,可以不需要切换到G1。切换到G1不要求更新JDK版本。2.2 实现概览2.2.1 老式垃圾回收器老式垃圾回收器(Serial,Parallel,CMS)统一将堆分成大小固定的三部分:新生代、老年代和永久代。整体划分类似如下图所示:2.2.2 G1 内存划分在G1垃圾回收器中,使用了不同的内存划分方法,其将内存划分为不同小的区域(region),每个区域在虚拟内存上是连续的。同时在实际使用中,每个区域会像老式垃圾回收器一样,标记该region为eden、survivor和old,但是某个区域不是固定属于区(eden等),其余依据实际使用动态地去调整。G1收集器将堆均分成大小相同的区域,每个区域的大小为1M~32M之间,最大支持2048个区域,因此G1最大可支持的内存为64G。可参考源码:https://github.com/wu560130911/jdk/blob/jdk8-b119/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp#L139//Minimumregionsize;wewon'tgolowerthanthat. //Wemightwanttodecreasethisinthefuture,todealwithsmall //heapsabitmoreefficiently. staticconstsize_tMIN_REGION_SIZE=1024*1024; //Maximumregionsize;wedon'tgohigherthanthat.There'sagood //reasonforhavinganupperbound.Wedon'twantregionstogettoo //large,otherwisecleanup'seffectivenesswoulddecreaseasthere //willbefeweropportunitiestofindtotallyemptyregionsafter //marking. staticconstsize_tMAX_REGION_SIZE=32*1024*1024; //Theautomaticregionsizecalculationwilltrytohavearoundthis //manyregionsintheheap. staticconstsize_tTARGET_REGION_NUMBER=2048;在不同堆大小写的区域大小如表格:堆大小region大小heap 4GB1M4GB = headp 8GB2M8GB = headp 16GB4M16GB = headp 32GB8M32GB = headp 64GB16Mheap = 64GB32M2.2.3 回收概要G1垃圾收集过程与CMS类似。G1在堆内存中并发地对所有对象进行标记,决定对象的可达性。经过全局标记,G1了解哪些区域几乎是空的,然后优先收集这些区域,这就是GarbageFirst的命名由来。G1将垃圾收集和内存整理活动专注于那些几乎全是垃圾的区域,并建立停顿预测模型来决定每次GC时回收哪些区域,以满足用户设定的停顿时间。对于区域的回收通过复制算法实现。在完成标记清理后,G1将这几个区域的存活对象复制到一个单独区域中,实现内存整理和空间释放。这一过程通过多线程并行进行来降低停顿时间,提高吞吐量。通过这样的方式,G1在每次GC过程中持续清理碎片,控制停顿时间满足用户要求。这是过去虚拟机无法做到的,CMS不清理内存碎片(除非通过虚拟机参数设置,在每次或多次FullGC后进行整理),ParallelOld进行全堆整理,会导致较长的停顿时间。G1不是实时垃圾收集器,它会尽量让停顿时间低于用户设置的停顿时间目标但不能保证一定如此。G1根据历史垃圾收集监测数据来 预测每个区域的回收时间,然后根据用户设定的目标停顿时间决定每次GC时可以回收哪些区域。G1通过 这种方式建立比较精确的区域回收时间预测模型。注意:G1有并发阶段(与应用线程并行,无停顿时间)和并行阶段(多线程,应用工作线程停顿)。FullGC仍是单线程,如果调优合适,可避免出现FullGC。2.2.4 特殊内存占用

更多文章