G1垃圾回收器原理

G1垃圾回收器适用于响应时间要求高的场景,它允预期停顿时间设置,控制STW时间。通过追踪Region回收价值,G1在有限时间内高效回收垃圾对象。G1将堆内存划分为Region,并动态分配新生代和老年代。新生代采用复制算法,老年代则依据对象年龄和Survivor区空间决定晋升。大对象可直接存入特定Region,避免占用老年代。使用-XX:+UseG1GC启用,其他参数如-XX:G1HeapRegionSize、-XX:GCPauseMills等用于调整行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现在一般的垃圾回收器都是选择ParNew+CMS的搭配,使用多线程并发回收可以有效降低STW(stop the world)时间,但是在一些响应时间比较短的场景下,STW的时间不可控就会造成一些影响,还有就是系统的机器内存很大的情况下,可能一次回收会有很多个G的垃圾需要回收,那么必然会导致垃圾回收时间较长。在这种情况下,就需要使用G1垃圾回收器,G1可以同时完成年轻代和老年代的回收,且可以指定我们所需要的STW的时间,防止系统长时间的卡顿。

G1把java堆内存拆分为了多个大小相等的Region,同时G1也存在新生代和老年代的逻辑概念,所以新生代和老年代都会包含一部分的Region。我们对于JVM垃圾回收的各种优化其实都是为了减少STW时间对于我们系统的影响,G1最大的特点就是可以设置一个预期的停顿时间,这样就相当于我们可以直接控制STW的时间,这就厉害了。

那么G1是如何做到控制垃圾回收的停顿时间的呢,G1会追踪所有Region的回收价值,回收价值的意思就是这个Region中包含了多少的垃圾对象,回收这些垃圾对象需要耗费多少的时间。在垃圾回收的过程中,G1通过我们设置的预期停顿时间,追踪每个Region的回收价值,在有限的时间内,去尽可能的多回收一些垃圾对象。

通过 -XX:+UseG1GC 参数就可以指定使用G1垃圾回收器了,G1里面的Region的数量是根据堆内存的大小自动计算的,默认情况下是堆内存/2048,假如我们的堆内存是4G,那么每个Region的大小就是2M,当然也可以通过参数-XX:G1HeapRigionSize 指定每个Rigion大小,一般使用默认的就好。

刚开始的时候,新生代所占内存默认是堆内存的5%,也可以通过-XX:G1NewSizePercent 指定G1初始化新生代的大小,系统在运行的过程中,不断给新生代分配越来越多的对象,新生代所占的Region也越来越多,但是不会超过堆内存的60%,这个也可以通过-XX:G1MaxNewSizePercent 参数指定G1新生代对堆内存最大占比。G1中的Region都是动态分配的,没有固定的说是新生代还是老年代,可能一个Region现在存放的年轻代的对象,过一会又变成了存放老年代的对象。

G1中的新生代也存在Eden区和Survivor区的概念,当需要触发新生代的垃圾回收时,使用的是复制算法,根据我们预设的停顿时间进行垃圾回收,可以通过 -XX:MaxGCPauseMills 参数设置,默认为200ms,然后清空Eden和一个Survivor区的Region,将存活的对象放入另一个Survivor区的Region中。

新生代垃圾回收之后,可能就会有一部分的存活对象需要进入到老年代,一般有两个条件,一个是经历了很多次Young GC,存活了一定岁数的对象,可以通过-XX:MaxTenuringThreshold参数设置,默认是15;另一个是动态年龄判定规则,一旦存活的对象超过了Survivor区的50%,比如1岁,2岁,3岁的存活对象大小大于Survivor区的50%,就把年龄大于3岁的对象都放入老年代中。

还有一种特殊的情况,在之前的ParaNew+CMS垃圾回收器中,如果年轻代的存活对象大于Survivor区的大小,则会直接进入老年代,但是在G1中,这种情况会有专门的Region来存放大对象,不需要再放入老年代中了,如果大对象的大小大于一个Region的大小的话,则会跨多个Region存放,在新生代,老年代垃圾回收的时候,会顺带着把大对象的Region一起回收。

G1中最重要的概念就是Region,所有的对象都是存放在Region中,进行动态分配,不需要我们手动去设置各种参数来调节,我们只需要设置我们能接受的停顿时间并告诉G1,G1就可以在指定时间内,通过每个Region的回收价值,来最大程度的进行垃圾回收,保证不会影响系统的正常运行。

G1(Garbage-First)垃圾回收器是一种面向服务端应用的垃圾回收器,它的工作原理如下: 1. 初始标记(Initial Mark):在此阶段,G1会暂停所有应用线程,标记所有根对象,并记录下所有从根对象直接可达的对象。 2. 并发标记(Concurrent Marking):在此阶段,G1会与应用线程并发工作,标记所有从根对象间接可达的对象。这个过程是增量进行的,即与应用线程交替执行,以减少对应用程序的停顿时间。 3. 最终标记(Final Mark):在此阶段,G1会再次暂停所有应用线程,完成并发标记阶段中未完成的对象标记。 4. 筛选回收(Live Data Counting and Evacuation):在此阶段,G1会根据堆中各个区域的回收价值进行筛选,确定哪些区域中的对象将被回收。然后,G1会将存活对象从这些区域中复制到空闲区域。 5. 复制(Humongous Copy):在此阶段,G1会将大对象(Humongous Objects)从一个区域复制到另一个区域。大对象是指超过一定阈值的对象,它们可能会导致碎片问题,G1通过复制来解决这个问题。 6. 清理(Cleanup):在此阶段,G1会清理已经被复制的区域,回收其中的未存活对象,使这些区域变为空闲状态。 7. 筛选回收(Live Data Counting and Evacuation):G1会再次进行筛选回收,重复步骤4和5,直到达到预设的回收目标。 G1垃圾回收器通过将堆内存分成多个大小相等的区域(Region),以增量的方式进行垃圾回收,从而减少应用程序的停顿时间,并且能够根据实际情况动态调整每个区域的大小,以适应不同应用的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值