专栏首页悠扬前奏的博客JVM-5. 垃圾回收器

JVM-5. 垃圾回收器

HotSpot中包含的收集器如下图所示:

HotSpot的垃圾收集器

1. Serial/ Serial Old收集器

  • 最基本,历史最久
  • 新生代采取复制算法,暂停所有用户线程
  • 老年代采取标记-整理算法,暂停所有用户线程
  • 单线程,进行垃圾收集时必须暂停其他所有工作线程
  • 最简单,单线程里面最高效
  • Client模式下默认新生代收集器

2. PerNew收集器

  • Serial收集器的多线程版本
  • Server模式下首选的新生代收集器
  • 除Serial收集器外,只有它能与CMS收集器配合工作
  • -XX:+UseConcMarkSweepGC选项之后默认的新生代收集器
  • -XX:UsePerNewGC强制指定
  • -XX:ParallelGCThreads参数限制垃圾收集器的线程数。

3. Parallel Scavenger收集器

  • 使用复制算法的收集器
  • 并行多线程收集器
  • 目标是达到一个可控的吞吐量(Throughput)
  • 精确控制吞吐量的参数:
    • -XX:MaxGCPauseMillis ,接受一个大于0的毫秒数,收集器将尽可能保证内存回收花费的时间不超过设定值。注意:时间越小,收集越频繁
    • -XXGCTimeRatio参数,直接设置吞吐量,接受一个大于0小于100的整数,即垃圾收集时间占总时间的比率,也就是吞吐量的倒数,默认值99,即默认最大1%的垃圾回收时间。
  • -XX:+UseAdaptiveSizePolicy,开关参数,打开之后不需要手工指定新生代的大小(-Xmm),Eden与Survivor比例(-XXSurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数,虚拟机根据当前系统运行情况收集性能监控信息,动态调整这些参数自适应调节(GC Ergonomics)最合适的停顿时间和最大吞吐量。

4. Serial Old收集器

  • Serial收集器的老年代版本
  • 单线程收集器
  • 使用“标记-整理”的办法
  • 在Client模式下作为虚拟机的默认老年代收集器
  • 在Server模式下可以和Parallel Scavenge收集器搭配
  • 在Server模式下作为CMS的后备,在并发时和Concurrent Mode Failure时使用

5. Parallel Old收集器

  • Parallel Scavenge收集器的老年代版本
  • 多线程处理
  • 使用“标记-整理”算法
  • 从JDK1.6开始提供
  • 在需要注意吞吐量和CPU资源敏感的时候优先考虑Parallel Scavenge+Parallel Old组合

6. CMS收集器

  • CMS = Concurrent Mark Sweep
  • 以获取最短回收停顿时间为目标
  • 适合在注意服务器响应速度,希望系统停顿时间最短,比如互联网网站或者B/S系统服务端。
  • 基于“标记-清除”
    • 初始标记(CMS initial mark)
      • 需要全暂停,但是仅仅标记GC Roots能关联到的对象,速度很快
    • 并发标记(CMS Concurrent mark)
      • 进行GC Roots Tracing的过程,和用户线程一起工作
    • 重新标记(CMS remark)
      • 全暂停
      • 为了修正并发标记期间用户线程导致的记录变化
      • 一般比初始标记长,远比并发标记时间短
    • 并发清除(CMS Concurrent sweep)
      • 和用户线程一起工作
  • 缺点在于:
    • 对于CPU资源和敏感,因在并发回收阶段会占用线程资源,会导致应用程序变慢,总吞吐量降低
      • 无法清除浮动垃圾(Floating Garbage)因为在垃圾回收阶段用户进程可能产生新的垃圾,但是出现在标记阶段之后,无法在当次处理,叫浮动垃圾。
      • CMS收集器需要预留空间提供并发收集时的程序运行,用-XX:CMSInitiatingOccupancyFraction设置触发收集的百分比,JDK1.5 默认68%,JDK1.6默认92%
      • CMS运行期间预留的内存无法满足程序需要,会临时启动Serial Old收集器重新进行老年代手机
  • 基于“标记-清楚”的算法会产生大量碎片
    • -XX:+UseCMSCompactAtFullCollection参数(默认开启),在FullGC时开启内存碎片的整合过程,解决空间碎片问题,但是停顿时间变长
    • -XX:CMSFullGCsBeforeCompaction:设置执行多少次不压缩的Full GC,再进行带压缩的(默认为0,标识每次Full GC时都需要进行碎片整理)

7. G1收集器

  • Garbage-First
  • 面向服务端应用
  • 并行与并发利用多个CPU来缩短Stop-The-World时间
  • 分代收集
  • 空间整合,从整体上基于“标记-整理”,聚不上基于“复制”,不会产生碎片
  • 可预测的停顿
  • 保留新生代和老年代的概念,但是它们之间不再物理隔离,都是一部分Region的集合。
  • 跟踪Region垃圾堆价值大小,后台维护优先列表,每次根据允许的收集时间,回收价值最大的Region。
  • 通过Remembered Set来避免全堆扫描,每个Region都有一个对应的Remembered Set。在Reference对象被写入时,中断写操作,检查Reference引用的对象是否处于不同的Region,如果是,通过CardTable把相关引用的信息记录到被引用对象所属的Region的Remembered Set中。
  • 除了维护Remembered Set的操作,G1收集器运作包括以下几个步骤:
    • 初始标记(Initial Marking):记录GC Roots能关联到的对象。时间短,中断用户操作。
    • 并发标记(Concurrent Marking),从GC Roots开始进行可达性分析,耗时较长,可并行
    • 最终标记(Final Marking),把并发标记期间对象变化记录在线程Remembered Set Logs中,并把其中的数据合并到Remembered Set中。需要停顿线程,但是可并行执行。
    • 筛选回收(Live Data Counting Evacuation)对各个Region的回收价值和成本进行排序,根据用户期望的GC停顿时间来指定回收计划。

8. GC日志

一般包括:

  • GC发生时间,一般用Java虚拟机启动经过的秒数
  • GC和“Full GC”,标识垃圾收集停顿类型,是否发生Stop-The-World
  • GC发生区域
  • GC钱内存区域使用容量->GC后内存区区域使用容量(内存区域总容量)
  • GC占用时间

9. 垃圾收集器参数

参数

描述

UseSerialGC

虚拟机在Client模式下的默认值,使用Serial+Serial Old收集器组合进行内存回收

UseParNewGC

打开后,使用ParNew+Serial Old的收集器组合进行内存回收

UseConcMarkSweepGC

打开后,使用ParNew + CMS + Serial Old的组合进行回收,其中Serial Old作为CMS收集器出现Concurrent Mode Failure失败后的后备收集器使用

UseParallelGC

在Server模式下的默认值,打开后使用Parallel Scavenge+Serial Old(PS MarkSweep)收集器组合进行回收

UseParallelOldGC

打开后,使用Parallel Scavenge + Parallel Old组合进行内存回收

SurvivorRatio

新生代中Eden区域和Survivor区域的容量比值,默认是8,也就是Eden:Survivor = 8:1

PretenureSizeThreshold

直接晋升到老年代的对象大小,设置这个参数之后,大于这个参数的对象将直接在老年代分配。

MaxTenuringThreshold

晋升到老年代的对象年龄,这个对象在坚持过一次Minor GC之后,年龄就增加1,当超过这个参数后进入老年代。

UseAdaptiveSizePolicy

动态调整Java堆中各个区域的大小以及进入老年代的年龄

HandlePromotionFailure

是否允许分配担保失败,即老年代的剩余空间不足以应付新生代的整个Eden和Survivor区的所有对象都存活的极端情况

ParallelGCThreads

设置并行GC时进行内存回收的线程数

GCTimeRatio

GC时间占总时间的比例,默认为99%,即允许1%的GC时间,仅在使用Parallel Scavenge收集器时有效

MaxGCPauseMillis

设置GC最大停顿时间,尽在使用Parallel Scavenge收集器时生效

CMSInitiatingOccupancyFraction

设置CMS在老年代空间被使用多少之后触发垃圾收集,默认为68%。仅在CMS收集器时生效

UseCMSCompactAtFullConllection

设置CMS收集器在完成垃圾收集后是否要进行一次内存整理,仅在CMS收集器时生效

CMSFullGCsBeforeCompaction

设置CMS收集器在进行若干次垃圾回收后再启动一次内存碎片整理,仅在CMS收集器时生效

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • LintCode-46.主元素

    给定一个整型数组,找出主元素,它在数组中的出现次数严格大于数组元素个数的二分之一。

    悠扬前奏
  • MyBatis-6.日志

    Mybatis 的内置日志工厂提供日志功能,内置日志工厂将日志交给以下其中一种工具作代理:

    悠扬前奏
  • Spring Boot-5.Favicon

    Spring Boot提供了默认的Favicon图表,和Spring的标志一样,一个绿色的叶子。 默认Favicon是开启的。

    悠扬前奏
  • 7 种 JVM 垃圾收集器,看完我跪了。。

    Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商、版本的虚拟机所提供的垃圾收集器都可能会有很大差别,并且一般都会提供参数供用户根据自己...

    黄泽杰
  • JVM学习记录-垃圾收集器

    纪莫
  • JVM系列三(垃圾收集器).

    上篇文章 我们介绍了 Java 内存运行时区域的各个部分,其中程序计数器、虚拟机栈、本地方法栈三个区域随线程而生,随线程而灭,在这几个区域内就不需要过多考虑回收...

    JMCui
  • 《深入理解java虚拟机》学习笔记4——Java虚拟机垃圾收集器

    http://blog.csdn.net/chjttony/article/details/7883748#comments

    bear_fish
  • Java虚拟机内存管理(五)-垃圾收集器

    不同版本的 JDK 选择的垃圾收集器也可能不同,我们在命令行查看安装的 JDK 的默认垃圾收集器,我这里是在 Windows 的 cmd 中输入 java -X...

    Wizey
  • JVM 垃圾收集器

    本文“垃圾收集器”节选自《深入理解Java虚拟机:JVM高级特性与最佳实践》【作者:周志明】

    smartsi
  • JVM复习笔记

    young generation-------serial, parnew, parallel scavenge tenured gencration-----...

    陈灬大灬海

扫码关注云+社区

领取腾讯云代金券