爱分享666

当前位置:首页 >java技术博客>java基础

G1收集器

      G1(Garbage-First)是JDK7-u4才推出商用的收集器;

1、特点

(A)、并行与并发

      能充分利用多CPU、多核环境下的硬件优势;

      可以并行来缩短"Stop The World"停顿时间;

      也可以并发让垃圾收集与用户程序同时进行

(B)、分代收集,收集范围包括新生代和老年代    

      能独立管理整个GC堆(新生代和老年代),而不需要与其他收集器搭配;

      能够采用不同方式处理不同时期的对象;

                

      虽然保留分代概念,但Java堆的内存布局有很大差别;

      将整个堆划分为多个大小相等的独立区域(Region);

      新生代和老年代不再是物理隔离,它们都是一部分Region(不需要连续)的集合;

(C)、结合多种垃圾收集算法,空间整合,不产生碎片

      从整体看,是基于标记-整理算法

      从局部(两个Region间)看,是基于复制算法

      这是一种类似火车算法的实现;

 

      都不会产生内存碎片,有利于长时间运行;

(D)、可预测的停顿:低停顿的同时实现高吞吐量

      G1除了追求低停顿处,还能建立可预测的停顿时间模型;

      可以明确指定M毫秒时间片内,垃圾收集消耗的时间不超过N毫秒;

2、应用场景

      面向服务端应用,针对具有大内存、多处理器的机器;

      最主要的应用是为需要低GC延迟,并具有大堆的应用程序提供解决方案;

      如:在堆大小约6GB或更大时,可预测的暂停时间可以低于0.5秒;

            

      用来替换掉JDK1.5中的CMS收集器

      在下面的情况时,使用G1可能比CMS好

      (1)、超过50%的Java堆被活动数据占用;

      (2)、对象分配频率或年代提升频率变化很大;

      (3)、GC停顿时间过长(长于0.5至1秒)。

      是否一定采用G1呢?也未必:

      如果现在采用的收集器没有出现问题,不用急着去选择G1;

      如果应用程序追求低停顿,可以尝试选择G1;

      是否代替CMS需要实际场景测试才知道。

3、设置参数

      "-XX:+UseG1GC":指定使用G1收集器;

      "-XX:InitiatingHeapOccupancyPercent":当整个Java堆的占用率达到参数值时,开始并发标记阶段;默认为45;

      "-XX:MaxGCPauseMillis":为G1设置暂停时间目标,默认值为200毫秒;

      "-XX:G1HeapRegionSize":设置每个Region大小,范围1MB到32MB;目标是在最小Java堆时可以拥有约2048个Region;

4、为什么G1收集器可以实现可预测的停顿

      G1可以建立可预测的停顿时间模型,是因为:

      可以有计划地避免在Java堆的进行全区域的垃圾收集

      G1跟踪各个Region获得其收集价值大小,在后台维护一个优先列表;

      每次根据允许的收集时间,优先回收价值最大的Region(名称Garbage-First的由来);

      这就保证了在有限的时间内可以获取尽可能高的收集效率;

5、一个对象被不同区域引用的问题

      一个Region不可能是孤立的,一个Region中的对象可能被其他任意Region中对象引用,判断对象存活时,是否需要扫描整个Java堆才能保证准确?

      在其他的分代收集器,也存在这样的问题(而G1更突出):

      回收新生代也不得不同时扫描老年代?

      这样的话会降低Minor GC的效率;

      解决方法:

      无论G1还是其他分代收集器,JVM都是使用Remembered Set来避免全局扫描

      每个Region都有一个对应的Remembered Set;

      每次Reference类型数据写操作时,都会产生一个Write Barrier暂时中断操作;

      然后检查将要写入的引用指向的对象是否和该Reference类型数据在不同的Region(其他收集器:检查老年代对象是否引用了新生代对象);

      如果不同,通过CardTable把相关引用信息记录到引用指向对象的所在Region对应的Remembered Set中;

                    

      当进行垃圾收集时,在GC根节点的枚举范围加入Remembered Set;

      就可以保证不进行全局扫描,也不会有遗漏。

6、G1收集器运作过程

      不计算维护Remembered Set的操作,可以分为4个步骤(与CMS较为相似)。

(A)、初始标记(Initial Marking)

      仅标记一下GC Roots能直接关联到的对象;

      且修改TAMS(Next Top at Mark Start),让下一阶段并发运行时,用户程序能在正确可用的Region中创建新对象;

      需要"Stop The World",但速度很快;

(B)、并发标记(Concurrent Marking)

      进行GC Roots Tracing的过程;

      刚才产生的集合中标记出存活对象;

      耗时较长,但应用程序也在运行;

      并不能保证可以标记出所有的存活对象;

(C)、最终标记(Final Marking)

      为了修正并发标记期间因用户程序继续运作而导致标记变动的那一部分对象的标记记录;

      上一阶段对象的变化记录在线程的Remembered Set Log;

      这里把Remembered Set Log合并到Remembered Set中;

                    

      需要"Stop The World",且停顿时间比初始标记稍长,但远比并发标记短;

      采用多线程并行执行来提升效率;

(D)、筛选回收(Live Data Counting and Evacuation)

      首先排序各个Region的回收价值和成本;

      然后根据用户期望的GC停顿时间来制定回收计划;

      最后按计划回收一些价值高的Region中垃圾对象;

                    

      回收时采用"复制"算法,从一个或多个Region复制存活对象到堆上的另一个空的Region,并且在此过程中压缩和释放内存;

      可以并发进行,降低停顿时间,并增加吞吐量;

      G1收集器运行示意图如下:

        

      到这里,我们大体了解HotSpot虚拟机中的所有垃圾收集器,后面我们将去了解JVM的一些内存分配与回收策略、JVM垃圾收集相关调优方法……


上一篇:

Java虚拟机垃圾回收器之Parallel Old收集器_应用场景

下一篇:

springboot _添加robots.txt帮助SEO优化_java框架

0 +1
打赏 ×

如果网站能给予您帮助,欢迎给网站捐助,给我打赏个吧!
您的支持是我的动力,让网站能一直陪伴着大家,共同学习进步。
捐助费用将用于网站日常运营(服务器租费、域名租费等)
捐助者请发送邮箱提供姓名至 zhaoqn@163.com 留言以表感谢。

网友评论


  • 验证码:

热门评论

本月热门

推荐资料

精彩评论

回到顶部