G1垃圾回收器简介
什么是G1
G1 也叫垃圾优先回收器,其主要含义是不会像传统垃圾回收器一样等到空间满了才会回收,而是在空间还没满时就进行了回收。
这样做的好处:每次垃圾回收时间短,吞吐量高。可以在用户指定的时间内完成垃圾回收。
G1的应用场景:主要面向多cpu和大内存服务器场景,电商秒杀服务器,多路直播服务器。
G1最大的特征:将大空间分成若干个小区域,能实现一些更复杂、更精细的功能。
G1与传统模型对比:
划分成小区域的好处:
- 垃圾回收线程和工作线程能够并行工作,避免STW。
- 不同区域可同时回收,并发性更高,更适合多核服务器。
- 可以先回收一部分区域,回收更快。
- 可以建立停顿预测模型,用户可以设定垃圾回收最长时间。
图解G1对象管理过程
当E区存放满时,存活对象移动到S区,然后进行YGC。
大对象:一般一个对象大于整个区域的一半则被称为大对象。
总结思考:
1.每个区域该多大?总数为多少比较好?
2.新生/老年代区域比例该如何才能最优?
3.大对象该如何管理?
4.除了YGC,还有几种类型,如何工作?
深入剖析G1-region划分原理
Region 区域总数和大小都是可变的。
数量方面,region默认总个数为2048个
大小方面,默认是1MB,可以通过参数将其修改为2、4、8、16和32MB这几种。
-
测试分区大小
-
测试分区类型
在G1里区域是有多种类型的:
新生代分区,存储新创建的对象的分区,默认大小是1MB,又可以分为Eden区和Survivor区。
老年代分区,存储生命周期比较长的对象,默认大小是1MB。
大对象分区,主要存储比较大的对象。
还有一种情况,有些对象特别大,甚至快占满一个分区了,此时如果仍然将其存储在新生代,那每次垃圾回收都要移动一次,这代价就太大了,所以我们干脆将其再放到一个统一的地方,这就是H区。
那什么样的对象才会放到H区呢?
答案是:如果对象大小大于等于分区的一半就会将其放到H区。 -
新生代和老年代分别占多少
我们注意到年轻代区域的个数是变化的,那新生代和老年代是怎么分配的呢?
答案是:默认情况下,新生代占比是动态变化的,新生代占堆空间的比例最小为5%,然后慢慢增加到最大为60%。
如何设置分区大小
如果想修改region的大小,可以通过 -XX:G1HeapRegionSize=4M来设置。
-XX:G1HeapRegionSize=4M -XX:+UseG1GC -XX:+PrintGCTimeStamps -XX:+PrintGCDetails
注意:分区大小只能采用2的指数倍的值。例如1/2/4/8/16/32MB等等,如果不是,则会向下取到最接近的值。例如如果设置的是31MB就会向下取16MB。
G1三种垃圾回收策略的概念与触发条件
三种方式分别是什么含义
- 新生代回收(YGC): 只回收新生代区域,代价低/频率高。
- 混合回收(MixGC): 回收全部新生代+部分老年代,频率一般。
- 完全回收(FullGC): 全部堆空间,代价高/频率低,系统离崩溃不远了。
三种方式分别在什么时候触发
新生代回收
YGC又分为Eden区和S区。新创建的对象先分配到Eden区,新生区满了就触发YGC。
思考GCRoots有哪些?
- 虚拟机栈中的变量引用
- 静态变量的引用
- 加锁的对象
- 常量池中的常量引用
停顿预测模型与垃圾区域的选择原理
混合回收的原理和步骤
混合回收和后面的FULL回收都是同时处理新生代和老年代区域。
对象什么时候会进入老年代?
- 如果一些对象经过几轮YGC仍然存活,或者触发了动态年龄判断规则
- 或者存活对象在S区放不下了,都会让对象进入老年代
- 大对象直接进入单独的大对象Region,但是大对象区域本身占用的就是老年代的区域。
混合回收并发标记为什么从YGC开始?
FullGC回收原理
FullGC 基本过程
- 标记活跃对象,然后计算对象的新地址
FullGC时,进入标记阶段,标记出所有的存货对象,这个过程与YGC MixedGC基本类似 - 更新引用对象的地址
逐个遍历每个Region,每个Region从头开始,找到存活的对象指向到接下来被回收的新位置。 - 更新引用对象的地址
上一步已经计算好每个对象新的地址了,那么此时就需要遍历所有存活对象,将对象间的引用也指向到新的位置上去。 - 复制对象
将对象真正复制到对象的新位置上去
- 复制后的处理
对回收工作进行收尾,例如调整整堆分区大小等等。
面试常问题收集:
-
G1 垃圾收集器了解么?
G1垃圾收集器的设计目标是在停顿时间可控的情况下,最大化系统吞吐量,它旨在提供更可控、更高效的垃圾回收性能。
以下是G1垃圾收集器的一些特点和工作原理:
a). 区域化内存布局:G1收集器将堆内存划分为多个大小相等的区域(region)。每个区域可以是Eden区、Survivor区或Old 区。这种内存布局有助于提高垃圾收集的效率。
b). 并行与并发 : G1收集器使用并行和并发的方式执行垃圾回收操作。它通过并行处理来加快标记和复制阶段的速度,同时利用并发处理来减少垃圾回收对应应用程序的停顿时间。
c).垃圾优先策略: G1收集器使用Garbage-First策略来确定优先处理哪些区域中的垃圾。它会根据区域中的垃圾数量、回收成本等因素来选择下一个要回收的区域,以最大程度地提高垃圾回收的效率。
d).混合回收: G1收集器执行混合回收,即同时处理新生代和老年代的垃圾回收。相比于传统的的分代式回收,它可以均衡地处理整个堆内存,避免长时间的FullGC暂停。
e).可预测的停顿时间: G1收集器使用一种停顿预测模型的机制,通过控制每次垃圾回收的时间目标来实现可预测的停顿时间。开发人员可以通过设置最大停顿时间来控制G1收集器的行为。 -
工作原理
-
初始标记:停顿所有的应用程序的线程,识别出GcRoots直接关联的对象,并标记这些对象。
-
并发标记:从第一步得到的标记点继续向下遍历对象图,标记所有被引用的存活对象,此步骤与应用程序并发运行。
-
最终标记:在并发标记完成后,再次停顿所有的应用程序线程,重新标记被改变的对象和整理存活对象的布局。
-
筛选回收:根据用户设定的回收目标,选取一个或多个Region进行垃圾回收,将这些Region中的存活对象(还有其他Region中被引用的对象)复制到新的Region中,即称为筛选回收。
G1垃圾收集器适用于具有大内存需求和低暂停时间要求的应用程序。但需要注意的是,G1收集器也有一定的局限性,比如在处理大量临时垃圾对象或存在大量跨区域引用时可能会导致性能下降。总的来说,G1垃圾收集器在java应用程序中的使用越来越广泛,特别适合那些对停顿时间敏感的大型服务端应用程序。
- FullGC场景
从年轻代分区拷贝存活对象时,无法找到可用的空闲分区
从老年代分区转移存活对象时,无法找到可用的空闲分区
分配巨型对象时在老年代无法找到足够的连续分区