Java虚拟机(四)--垃圾收集器之G1收集器

    随着Java9的发布,G1收集器也成为了默认收集器,作为前沿技术,研究下还是很有必要的,通过查阅很多资料,整理我觉得比较适合初学者理解的G1收集器。

   一 先了解一些必要的概念。

    1 Region

        G1收集器将堆内存分为大小相等的若干个region,采用逻辑分代概念。分为Eden、Survivor、Old、Humongous四个区域。

           这里主要说下陌生的Humongous区域:如果该对象的大小大于当前region的一半时,将存入这个区域,这个区域属于Old,目的是为了防止反复拷贝移动。

    2 Card 及 Rset(Remembered Set)

        每个region又分为若干个大小相等的card,大小在128byte~512byte之间,对象占用一个或者多个连续的card上,每个region中又有一个Rset,其维护着其它Region中的对象对本对象的引用。G1的RSet是在Card Table的基础上实现的:每个Region会记录下别的Region有指向自己的指针,并标记这些指针分别在哪些Card的范围内。 这个RSet其实是一个Hash Table,Key是别的Region的起始地址,Value是一个集合,里面的元素是Card Table的Index.

    理解了上边两个概念我们在回来看G1,用Region目的时为了建立时间可预测模型,在短时间内进行最大效率的垃圾回收。而对象可达性判断上面临一个问题,如果全堆扫描的话会浪费很多时间,所以有了Rset,典型的空间换时间。

    二 G1收集器的优点(摘自《深入理解Java虚拟机》周志明著》

        并行与并发:G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短Stop-The-World停顿的时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让Java程序继续执行。

        分代收集:与其他收集器一样,分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。

        空间整合:与CMS的“标记—清理”算法不同,G1从整体来看是基于“标记—整理”算法实现的收集器,从局部(两个Region之间)上来看是基于“复制”算法实现的,但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。

        可预测的停顿:这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。

    三 执行过程

        初始标记(initial mark,STW)。它标记了从GC Root开始直接可达的对象。

        并发标记(Concurrent Marking)。这个阶段从GC Root开始对heap中的对象标记,标记线程与应用程序线程并行执行,并且收集各个Region的存活对象信息。

        最终标记(Remark,STW)。标记那些在并发标记阶段发生变化的对象,将被回收。

        清除垃圾(Cleanup)。清除空Region(没有存活对象的)。

    如果大家想看更深层次的可以看下这两篇文章:

        详解 JVM Garbage First(G1) 垃圾收集器

        Java Hotspot G1 GC的一些关键技术

        G1垃圾回收器详解

    

猜你喜欢

转载自blog.csdn.net/weixin_41574643/article/details/80250042