G1 垃圾回收器介绍
G1 垃圾回收器是一款次要面向服务端利用的垃圾收集器。作为垃圾回收器技术发展史上里程碑的成绩,G1 垃圾回收器不同于以往的垃圾回收器,首先是思维上的转变,如下图:
G1 对于 Java 堆的划分
下面的图,小伙伴们第一次看可能不咋明确,因为各位还不理解 G1,看看上面的话,应该就差不多了。
G1 垃圾回收器对于 Java 堆区域的划分不同于以往咱们对 Java 对区域划分的认知
以往对于 Java 堆区域的划分 为:新生代和老年代,新生代又划分为 Eden 区和 Survivor 区,Survivor 区又分为 from 区和 to 区。
然而当初,G1 不再保持固定大小以及固定数量的分代区域划分 ,而是 把间断的 Java 堆空间划分为多个大小相等的独立区域(Region),每个 Region 都能够成为 Eden 空间、Survivor 空间、老年代空间。
这种思维上的转变和设计,使得G1 能够面向堆内存任何局部来组成回收集来进行回收,衡量标准不再是它属于哪个分代,而是哪块内存寄存的垃圾最多,回收收益最大,这就是 G1 收集器的 Mixed GC 模式,即混合 GC 模式。
Region 还有一类非凡的 Humongous 区域 , 专门用来存储大对象 。G1 认为 只有大小超过了一个 Region 容量一半的对象即可断定为大对象 。 如果是那些超过了整个 Region 容量的超大对象,将会放在间断 N 个 Humongous Region 区域。
Region 的取值范畴为 1M ~ 32M
Region 的默认个数为 2048 个
-XX:G1HeapRegionSize = N
G1 这么做看起来是由一种面目一新的感觉,但仔细的小伙伴可能曾经发现,如果 Region 之间存在跨区援用对象,那这些对象如何解决?
- 不论是 G1 还是其余分代收集器,JVM 都是应用 记忆集(Remembered Set) 来防止全局扫描。
- 每个 Region 都有一个对应的记忆集。
- 每次 Reference 类型数据写操作时,都会产生一个 写屏障(Write Barrier)临时去终止操作
- 而后查看将要写入的援用 指向的对象是否和该 Reference 类型数据在不同的 Region(其余收集器:查看老年代对象是否援用了新生代对象)
- 如果不同,通过 卡表(Card Table)把相干援用信息记录到援用指向对象的所在 Region 对应的记忆集(Remembered Set) 中
- 当进行垃圾收集时,在 GC Roots 枚举范畴加上记忆集;就能够保障不进行全局扫描了。
G1 的记忆集能够了解为一个哈希表,Key 就是别的 Region 的起始地址,Value 就是卡表的索引号汇合。
因为 G1 将 Java 堆划分为一个个 Region 的缘故,而 Region 数量相比于传统分代数量显著多得多,所以 G1 相比于传统的垃圾回收器来说,须要耗费相当于 Java 堆容量 10%~ 20% 的额定空间来维持收集器的工作。
G1 垃圾回收器工作流程
- 初始标记 (Initial Marking):这阶段 仅仅只是标记 GC Roots 能间接关联到的对象并批改 TAMS(Next Top at Mark Start)的值 ,让下一阶段用户程序并发运行时,能在正确的可用的 Region 中创立新对象,这阶段 须要进展线程,然而耗时很短。而且是借用进行 Minor GC 的时候同步实现的,所以 G1 收集器在这个阶段理论并没有额定的进展。
- 并发标记 (Concurrent Marking): 从 GC Roots 开始对堆的对象进行可达性剖析,递归扫描整个堆里的对象图,找出存活的对象 ,这阶段耗时较长,然而能够与用户程序并发执行。当对象图扫描实现当前,还要 重新处理 SATB 记录下的在并发时有援用变动的对象。
- 最终标记 (Final Marking):对用户线程做另一个短暂的暂停, 用于解决并发阶段完结后仍遗留下来的最初那大量的 SATB 记录。
- 筛选回收 (Live Data Counting and Evacuation): 负责更新 Region 的统计数据,对各个 Region 的回收价值和老本进行排序 ,依据用户所冀望的进展工夫来制订回收打算。 能够自由选择多个 Region 来形成会收集,而后把回收的那一部分 Region 中的存活对象 == 复制 == 到空的 Region 中,在对那些 Region 进行清空。
除了并发标记外,其余过程都要 STW
G1 和 CMS 的区别
- G1 从整体上来看是 标记 - 整顿 算法,但从部分(两个 Region 之间)是复制算法。而 CMS 是 标记 - 革除算法 所以说,G1 不会产生内存碎片,而 CMS 会产生内存碎片
- CMS 应用了 写后屏障来保护卡表,而 G1 不仅应用了写后屏障来保护卡表,还是用了 写前屏障来跟踪并发时的指针变动状况(为了实现原始快照)。
- CMS 对 Java 堆内存应用的是传统的 新生代和老年代划分办法,而 G1 应用的全新的划分办法。
- CMS 收集器只收集老年代,能够配合新生代的 Serial 和 ParNew 收集器一起应用。G1 收集器收集范畴是老年代和新生代。不须要联合其余收集器应用
- CMS 应用 增量更新解决并发标记下呈现的谬误标记问题,而 G1 应用原始快照解决
最初
我是 Code 皮皮虾,一个酷爱分享常识的 皮皮虾爱好者,将来的日子里会不断更新出对大家无益的博文,期待大家的关注!!!
创作不易,如果这篇博文对各位有帮忙,心愿各位小伙伴能够 == 一键三连哦!==,感激反对,咱们下次再见~~~
== 分享纲要 ==
大厂面试题专栏
Java 从入门到入坟学习路线目录索引
开源爬虫实例教程目录索引