• 1.回顾CMS

    • 1.1堆内存结构
    • 1.2新生代GC
    • 1.3老年代GC
  • 2.G1收集器
    • 2.1G1实现概览及使用场景

      • G1的推荐使用场景
    • 2.2GC
    • 2.2.1新生代GC
    • 2.2.2老年代GC
      • 老年代GC总结
    • 2.2.3 其他
    • 2.4 最佳实践
      • 2.4.1 JVM参数

        • 基本参数设置
        • 关键参数设置
  • 3.参考资料

1.回顾CMS

1.1堆内存结构

新生代分为Eden区和两个survivor区。老年代是一块连续区域。

只有FullGC时才可能发生内存整理。

1.2新生代GC

新生代淡绿色,老年代蓝色。系统运行一段时间后CMS堆内存可能如下图所示,对象分散在老年代各处。

新生代存活对象从Eden区和survivor区复制到另一个空闲的survivor区。任何minorGC年龄达到阈值的老对象被升级至老年代。

youngGC(minorGC)后,Eden区和一个survivor区被清空。

新近升级至老年代的对象以深蓝色表示。绿色对象是新生代仍存活的对象。

1.3老年代GC

在初始标记和重新标记阶段发生STW。当老年代剩余空间达到阈值时(发生Concurrent Mode Failure),使用SerialOld替代CMS进行老年代GC。

(1)初始标记停顿时间很短,简单的标记GCRoot引用的对象。(2)并发标记在标记存活对象时,应用继续执行。(3)重新标记阶段,标记并发阶段遗漏的存活对象。

未被标记的对象直接被回收。完成并发清扫后,许多老年代空间被释放出来。同时内存整理仍没有发生,老年代存在大量内存碎片。

最终,CMS经过重置阶段,等待下一次GC。

2.G1收集器

2.1G1实现概览及使用场景

老式垃圾回收器(Serial,Parallel,CMS)统一将java堆分成大小固定的三部分:新生代、老年代和永久代。所有内存对象最终都保存在这三个区域内。

G1收集器将java堆均分成大小相同的区域(region,1M-32M,最多2000个,最大支持堆内存64G)。一个或多个不连续的区域共同组成eden、survivor或old区,但大小不再固定,这为内存应用提供了极大地弹性。G1垃圾收集过程与CMS类似。G1在堆内存中并发地对所有对象进行标记,决定对象的可达性。经过全局标记,G1了解哪些区域几乎是空的,然后优先收集这些区域,这就是GarbageFirst的命名由来。G1将垃圾收集和内存整理活动专注于那些几乎全是垃圾的区域,并建立停顿预测模型来决定每次GC时回收哪些区域,以满足用户设定的停顿时间。

对于区域的回收通过复制算法实现。在完成标记清理后,G1将这几个区域的存活对象复制到一个单独区域中,实现内存整理和空间释放。这一过程通过多线程并行进行来降低停顿时间,提高吞吐量。通过这样的方式,G1在每次GC过程中持续清理碎片,控制停顿时间满足用户要求。这时过去虚拟机无法做到的。CMS不清理内存碎片(除非通过虚拟机参数设置,在每次或多次FullGC后进行整理),ParallelOld进行全堆整理,会导致较长的停顿时间。

G1不是实时垃圾收集器,它会尽量让停顿时间低于用户设置的停顿时间目标但不能保证一定如此。G1根据历史垃圾收集监测数据来 预测每个区域的回收时间,然后根据用户设定的目标停顿时间决定每次GC时可以回收哪些区域。G1通过这种方式建立比较精确的区域回收时间预测模型。

G1的推荐使用场景

G1的设计初衷是为用户提供大内存、低GC停顿时间的应用解决方案。这意味着堆内存6G或更大,停顿时间稳定且少于0.5秒。

如果应用正在使用CMS或ParallelOld且面临以下问题,推荐将应用迁移至G1

  • FullGC发生频繁或总时间过长
  • 对象分配率或对象升级至老年代的比例波动较大
  • 较长的垃圾收集或内存整理停顿(大于0.5至1秒)

注意:如果应用没有上述问题,不需要迁移虚拟机。G1并不是最新JDK要求的虚拟机。

2.2GC

2.2.1新生代GC

存活对象移动到一个或多个survivor区域。如果对象达到晋升年龄,将被移动到老年代区域。

新生代GC总结:

  • 新生代垃圾回收(youngGC)需要STW,所有应用线程需要停顿。

  • youngGC多线程并行执行。

  • 存活对象复制到新的survivor区或老年代区。

2.2.2老年代GC

阶段
描述
说明

初始标记

(Stop the world)

标记GC Roots直接引用的对象,新生代直接引用的老年代对象。

并发标记

标记堆中所有存活的对象。与用户的应用程序并发执行。

在并发标记阶段,若发现区域对象中的所有对象都是垃圾,那个这个区域会在重新标记阶段被立即回收。

同时,并发标记过程中,会计算每个区域的对象活性(区域中存活对象的比例)。

重新标记

(Stop the world)

修正并发标记阶段因用户程序继续运行而导致标记发生变动的那一部分标记记录

如果发现完全没有活对象的region就会将其回收到空闲列表。

清除

(Stop the world)

清点和重置阶段。

1)使用marking bitmap统计每个region被标记为活的对象有多少,统计每个区域的对象活性(区域中存活对象的比例)。

2)重置Remembered Sets

 

复制

(Stop the world)

将存活的对象复制到未使用的region中。

G1选择那些活跃度最低,回收速度最快的区域进行回收。

老年代GC总结

  • 并发标记阶段

    • 区域活跃度信息的统计与应用线程并发进行
    • 活跃度信息决定了那个区域最先在清理阶段被回收
    • 没有CMS的清理阶段
  • 再次标记阶段
    • SATB算法比CMS使用的算法更快
    • 空区域在这个阶段被回收
  • 复制/清理阶段
    • 新生代和老年代同时被回收
    • 老年代根据活跃度确定回收优先级

2.2.3 其他

Remembered Set(可认为是GC Roots的补充)

每一个Region都有一个对应的Remembered Set,里面记录了所有来自外部的引用,这些引用将被认为是GC roots的补充。

G1收集器中,Region之间的对象引用以及其他收集器中的新生代和老年代之间的对象引用是使用Remembered Set来避免扫描全堆。
G1中每个Region都有一个与之对应的Remembered Set,虚拟机发现程序对Reference类型数据进行写操作时,会产生一个Write Barrier暂时中断写操作,检查Reference引用的对象是否处于不同的Region之间(在分代中例子中就是检查是否老年代中的对象引用了新生代的对象),如果是便通过CardTable把相关引用信息记录到被引用对象所属的Region的Remembered Set中。当内存回收时,在GC根节点的枚举范围加入Remembered Set即可保证不对全局堆扫描也不会有遗漏。

2.4 最佳实践

2.4.1 JVM参数

基本参数设置

启用G1 -XX:+UserG1GC
以下是使用G1收集器的javademo演示
java -Xmx50m -Xms50m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar

关键参数设置

  • -XX:+UseG1GC - 启用G1
  • -XX:MaxGCPauseMillis=200 - GC停顿的最长时间。这是一个软目标,即虚拟机会尽最大可能满足这一时间,但某些情况下仍可能超过。默认值为200ms。
  • -XX:InitiatingHeapOccupancyPercent=45 - 堆内存使用率达到多少时启动一次GC过程。GC过程涉及整个堆内存,不单指某个年龄代。设为0时表示循环进行并发GC。默认值为45,即堆内存使用45%后触发一次GC。

3.参考资料

http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/G1GettingStarted/index.html  Getting Started with the G1 Garbage Collector

https://www.cnblogs.com/oldtrafford/p/6883796.html Getting Started with the G1 Garbage Collector(中文)

https://www.jianshu.com/p/74dd0ffd4386?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation Java垃圾回收手册(四):垃圾回收算法实现

http://blog.jobbole.com/109170/ 深入理解Java G1垃圾收集器

http://hllvm.group.iteye.com/group/topic/44381 高级语言虚拟机论坛 [资料] [HotSpot VM] 请教G1算法的原理

深入理解JVM 垃圾收集器(下)G1收集器的更多相关文章

  1. CMS收集器和G1收集器优缺点

    首先要知道 Stop the world的含义(网易面试):不管选择哪种GC算法,stop-the-world都是不可避免的.Stop-the-world意味着从应用中停下来并进入到GC执行过程中去. ...

  2. JVM-如何判断对象存活与否与CMS收集器和G1收集器的区别

    JVM如何判断对象存活? 1.计数器 2.可达性分析   (很多主流语言采用这种方法来判断对象是否存活) 计数器:每当有一个地方引用该对象时,计数器 +1:引用失效则 -1: 优点:实现简单,判定效率 ...

  3. CMS收集器和G1收集器 他们的优缺点对比 G1只有并发标记才不会stop-the-world 其他都会停下来(阿里多次问到)

    CMS收集算法 参考:图解 CMS 垃圾回收机制原理,-阿里面试题 G1收集算法 参考:G1 垃圾收集器入门 首先要知道 Stop the world的含义(网易面试):不管选择哪种GC算法,stop ...

  4. 垃圾收集器之:G1收集器

    G1垃圾收集器是一种工作在堆内不同分区上的并发收集器.分区既可以归属于老年代,也可以归属新生代,同一个代的分区不需要保持连续.为老年代设计分区的初衷是我们发现并发后台线程在回收老年代中没有引用的对象时 ...

  5. CMS垃圾收集器与G1收集器

    1.CMS收集器 CMS收集器是一种以获取最短回收停顿时间为目标的收集器.基于“标记-清除”算法实现,它的运作过程如下: 1)初始标记 2)并发标记 3)重新标记 4)并发清除 初始标记.从新标记这两 ...

  6. CMS收集器和G1收集器

    CMS收集器 CMS收集器是一种以获取最短回收停顿时间为目标的收集器.基于"标记-清除"算法实现,它的运作过程如下: 初始标记 并发标记 重新标记 并发清除 初始标记.从新标记这两 ...

  7. G1收集器-原创译文[未完成]

    G1收集器-原创译文 原文地址 Getting Started with the G1 Garbage Collector 目的 本文介绍了如何使用G1垃圾收集器以及如何与Hotspot JVM一起使 ...

  8. G1收集器

    转载:https://blog.csdn.net/zhou2s_101216/article/details/79202893 http://blog.jobbole.com/109170/ http ...

  9. JVM垃圾收集器-G1收集器

    G1收集器是当前收集器技术发展的最前沿成果,在JDK1.6_Updata14中提供了Early Access版本的G1收集器以供适用.G1收集器是垃圾收集器理论进一步发展的产物,它与前面的CMS收集器 ...

随机推荐

  1. dropload 使用表

    移动端下拉刷新.上拉加载更多插件 依赖 (dependence) Zepto 或者 jQuery 1.7以上版本,推荐jQuery 2.x版本(二者不要同时引用) Zepto or jQuery 1. ...

  2. JavaScript------日期和时间戳的相互转换

    var date = new Date(); 日期转时间戳 Number(date)或者date.getTime(); //只是转换成了纯数字的时间戳,例如:1498144203861需要转换才能使用 ...

  3. Dubbo基础篇-zookeeper安装(单点)

    安装步骤: 一首先安装jdk环境 二 安装zookeeper   在centos虚拟机192.168.23.131中安装zookeeper: 1 修改操作系统/etc/hosts 文件中的配置: # ...

  4. Caused by: java.lang.IllegalArgumentException: @EnableAsync annotation metadata was not injected

    需要注意的是ComponentScan 不能扫描 org.springframework 否则会报错,要扫描指定的package才行

  5. 滚动监听: bootstrap 的scrollspy

    滚动监听 bootstrap 的scrollspy,需要借助.nav样式,活动的部分是加 .active类.本身导航没有position:fixed,需要自己加入 滚动监听.只有滚动和监听,只有默认锚 ...

  6. CoordinatorLayout Behaviors使用说明[翻译]

    翻译与:Intercepting everything with CoordinatorLayout Behaviors 使用过Android Design Support Library的小伙伴应该 ...

  7. delphi 事件记录

    delphi常用事件 序号 事件 描述 1. OnActive 焦点称到窗体或控件时发生 2. OnClick 鼠标单击事件 3. OnDbClick 鼠标双击事件 4. OnClose和OnClos ...

  8. MySQL Connector/C++ C++连接mysql

    MySQL :: MySQL Connector/C++ Developer Guide :: 1 Introduction to Connector/C++ https://dev.mysql.co ...

  9. 我的Android进阶之旅------>RxJava学习资料汇总

    在响应式编程中,应该牢记以下两点: everything is a stream(一切皆流) don't break the chain(不要打断链式结构) 记住,可观测序列就像一条河,它们是流动的. ...

  10. Python基础-面向对象1

    class Bar: def fansik(self, name, age): print(name, age) obj = Bar() print(obj.fansik('fanjinbao', 1 ...