转载自  深入JVM虚拟机(四) Java GC收集器

1 GC收集器

1.1 Serial串行收集器

串行收集器主要有两个特点:第一,它仅仅使用单线程进行垃圾回收;第二,它独占式的垃圾回收。

在串行收集器进行垃圾回收时,Java 应用程序中的线程都需要暂停(“StopThe World”),等待垃圾回收的完成,这样给用户体验造成较差效果。虽然如此,串行收集器却是一个成熟、经过长时间生产环境考验的极为高效的收集器。新生代串行处理器使用复制算法,实现相对简单,逻辑处理特别高效,且没有线程切换的开销。在诸如单 CPU 处理器或者较小的应用内存等硬件平台不是特别优越的场合,它的性能表现可以超过并行回收器和并发回收器。在 HotSpot 虚拟机中,使用-XX:+UseSerialGC 参数可以指定使用新生代串行收集器和老年代串行收集器。

-  新生代、老年代使用串行回收。

-  新生代使用复制算法。

-  老年代使用标记-压缩算法。

新生代日志输出:

0.844: [GC 0.844: [DefNew: 17472K->2176K(19648K), 0.0188339secs] 17472K->2375K(63360K), 0.0189186 secs] [Times: user=0.01 sys=0.00,real=0.02 secs]

8.259: [Full GC 8.259: [Tenured: 43711K->40302K(43712K),0.2960477 secs] 63350K->40302K(63360K), [Perm : 17836K->17836K(32768K)],0.2961554 secs]

[Times: user=0.28 sys=0.02, real=0.30 secs]

1.2 ParNew并行收集器

并行收集器是工作在新生代的垃圾收集器,它只简单地将串行回收器多线程化。它的回收策略、算法以及参数和串行回收器一样。并行回收器也是独占式的回收器,在收集过程中,应用程序会全部暂停。

但由于并行回收器使用多线程进行垃圾回收,因此,在并发能力比较强的 CPU上,它产生的停顿时间要短于串行回收器,而在单 CPU 或者并发能力较弱的系统中,并行回收器的效果不会比串行回收器好,由于多线程的压力,它的实际表现很可能比串行回收器差。开启并行回收器可以使用参数-XX:+UseParNewGC,该参数设置新生代使用并行收集器,老年代使用串行收集器。使用-XX:ParallelGCThreads 限制线程数量。

ParNew并行收集器日志输出:

0.834:[GC 0.834: [ParNew:13184K->1600K(14784K), 0.0092203 secs] 13184K->1921K(63936K), 0.0093401secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

1.3 Parallel收集器

Parallel收集器类假于ParNew并行收集器,它使用复制算法的收集器。从表面上看,它和并行收集器一样都是多线程、独占式的收集器。但是,并行回收收集器有一个重要的特点:它非常关注系统的吞吐量。

Parallel收集器可以使用以下参数启用:

-XX:+UseParallelGC:新生代使用并行回收收集器,老年代使用串行收集器。

-XX:+UseParallelOldGC:新生代和老年代都是用并行回收收集器。

这两个参数是矛盾的。因为停顿时间和吞吐量不可能同时调优:

-XX:MaxGCPauseMills:最大停顿时间,单位毫秒。GC尽力保证回收时间不超过设定值。

-XX:GCTimeRatio:垃圾收集时间占总时间的比,0-100的取值范围,默认99,即最大允许1%时间做GC。

Parallel收集器日志输出:

1.500:[Full GC [PSYoungGen:2682K->0K(19136K)] [ParOldGen: 28035K->30437K(43712K)] 30717K->30437K(62848K) [PSPermGen:10943K->10928K(32768K)], 0.2902791 secs] [Times: user=1.44 sys=0.03,real=0.30 secs]

1.4 CMS 收集器

CMS 是 Concurrent Mark Sweep 的缩写,意为并发标记清除,从名称上可以得知,它使用的是标记-清除算法,同时它又是一个使用多线程并发回收的垃圾收集器。与并行回收收集器不同,CMS 收集器主要关注于系统停顿时间。

CMS 工作时,主要步骤有:

初始标记(CMS initial mark): 根可以直接关联到的对象,速度比较快。

并发标记(CMS concurrent mark):主要标记过程,标记全部对象。注:和用户线程一起并发运行。

重新标记(CMS remark): 由于并发标记时,用户线程依然运行,因此在正式清理前,再做修正。

并发清除和并发重置(CMS concurrent sweep): 基于标记结果,直接清理对象。

其中初始标记和重新标记是独占系统资源的,而并发标记、并发清除和并发重置是可以和用户线程一起执行的。因此,从整体上来说,CMS 收集不是独占式的,它可以在应用程序运行过程中进行垃圾回收。

CMS 收集器在其主要的工作阶段虽然没有暴力地彻底暂停应用程序线程,但是由于它和应用程序线程并发执行,相互抢占 CPU,所以在 CMS 执行期内对应用程序吞吐量造成一定影响。CMS 默认启动的线程数是(ParallelGCThreads+3)/4),ParallelGCThreads 是新生代并行收集器的线程数,也可以通过-XX:ParallelCMSThreads 参数手工设定 CMS的线程数量。当 CPU 资源比较紧张时,受到 CMS收集器线程的影响,应用程序的性能在垃圾回收阶段可能会非常糟糕。

标记-清除算法将会造成大量内存碎片,离散的可用空间无法分配较大的对象。在这种情况下,即使堆内存仍然有较大的剩余空间,也可能会被迫进行一次垃圾回收,以换取一块可用的连续内存,这种现象对系统性能是相当不利的,为了解决这个问题,CMS 收集器还提供了几个用于内存压缩整理的算法。

-XX:+UseCMSCompactAtFullCollection参数可以使 CMS 在垃圾收集完成后,进行一次内存碎片整理。内存碎片的整理并不是并发进行的。

-XX:CMSFullGCsBeforeCompaction参数可以用于设定进行多少次 CMS 回收后,进行一次内存压缩。

-XX:ParallelCMSThreads设定CMS的线程数量。

CMS收集器日志输出:

1.662: [GC [1 CMS-initial-mark: 28122K(49152K)] 29959K(63936K), 0.0046877 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]

1.666: [CMS-concurrent-mark-start]

1.699: [CMS-concurrent-mark: 0.033/0.033 secs] [Times: user=0.25 sys=0.00, real=0.03 secs]

1.699: [CMS-concurrent-preclean-start]

1.700: [CMS-concurrent-preclean: 0.000/0.000 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]

1.700: [GC[YG occupancy: 1837 K (14784 K)]1.700: [Rescan(parallel) , 0.0009330 secs]1.701: [weak refs processing, 0.0000180 secs]

[1 CMS-remark:28122K(49152K)] 29959K(63936K), 0.0010248 secs] [Times: user=0.00 sys=0.00,real=0.00 secs]

1.702: [CMS-concurrent-sweep-start]

1.739: [CMS-concurrent-sweep: 0.035/0.037 secs] [Times: user=0.11 sys=0.02, real=0.05 secs]

1.739: [CMS-concurrent-reset-start]

1.741:[CMS-concurrent-reset:0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

CMS特点:

-  尽可能降低停顿

-  会影响系统整体吞吐量和性能

比如,在用户线程运行过程中,分一半CPU去做GC,系统性能在GC阶段,反应速度就下降一半

-  清理不彻底

因为在清理阶段,用户线程还在运行,会产生新的垃圾,无法清理。

因为和用户线程一起运行,不能在空间快满时再清理。

-XX:CMSInitiatingOccupancyFraction设置触发GC的阈值

如果不幸内存预留空间不够,就会引起concurrent mode failure,产生这种问题,通常都使用串行收集器再次垃圾收集,在这种情况下内存基本被占用满了,通常GC停顿的时间较长。

CMS收集器日志输出:

33.348: [Full GC 33.348: [CMS33.357: [CMS-concurrent-sweep:0.035/0.036 secs] [Times: user=0.11 sys=0.03, real=0.03 secs]

(concurrentmode failure): 47066K->39901K(49152K), 0.3896802 secs]60771K->39901K(63936K), [CMS Perm : 22529K->22529K(32768K)], 0.3897989secs] [Times: user=0.39 sys=0.00, real=0.39 secs]

1.5 G1收集器(Garbage First)

G1收集器与前面的CMS收集器相比有两个显著的改进:一是G1收集器是基于“标记-整理”算法实现的收集器,也就是说它不会产生空间碎片,这对于长时间运行的应用系统来说非常重要。二是它可以非常精确地控制停顿,既能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。G1收集器可以实现在基本不牺牲吞吐量的前提下完成低停顿的内存回收,这是由于它能够极力地避免全区域的垃圾收集,之前的收集器进行收集的范围都是整个新生代或老年代,而G1将整个Java堆(包括新生代、老年代)划分为多个大小固定的独立区域(Region),并且跟踪这些区域里面的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收垃圾最多的区域(这就是Garbage First名称的来由)。区域划分及有优先级的区域回收,保证了G1收集器在有限的时间内可以获得最高的收集效率。

2 GC收集器参数

2.1 收集器参数总结

1、 Serial串行收集器相关的参数

-XX:+UseSerialGC

新生代和老年代使用串行回收器。

-XX:SurvivorRatio

设置eden区大小和survivior区大小的比例。

-XX:PretenureSizeThreshold

设置大对象直接进入老年代的阈值。当对象的大小超过这个值时,将直接在老年代分配。

-XX:MaxTenureSizeThreshold

设置对象进入老年代的年龄的最大值。每一次Minor

2、 ParNew并行收集器相关的参数

-XX:+UseParNewGC

在新生代使用并行收集器。

-XX:+UseParallelGC

新生代使用并行回收收集器

-XX:+UseParallelOldGC

老年代使用并行回收器。

-XX:ParallelGCThreads

设置用于垃圾回收的线程数。通常情况下可以和CPU数量相等,但在CPU数量比较多的情况下,设置相对较小的数值也是合理的。

-XX:MaxGCPauseMills

设置最大垃圾收集停顿时间。它的值是一个大于0的正数。收集器在工作时,会调整java堆大小或者其他一些参数,尽可能地把停顿时间控制在MaxGCPauseMills以内。

-XX:GCTimeRatio

设置吞吐量大小。它的值时一个0到100之间的整数。假设GCTimeRatio的值为n,那么系统将花费不超过1/(1+n)的时间用于垃圾收集。

-XX:+UseAdaptiveSizePolicy

打开自适应GC策略。在这种模式下,新生代的大小、eden和survivior的比例、晋升老年代的对象年龄等参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。

3、 CMS 收集器相关的参数

-XX:+UseConcMarkSweepGC

新生代使用并行收集器,老年代使用CMS+串行收集器。

-XX:ParallelCMSThreads

设定CMS的线程数量。

-XX:CMSInitiatingOccupancyFraction

设置CMS收集器在老年代空间被使用多少后触发,默认为68%。

-XX:+UseCMSCompactAtFullCollection

设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片整理。

-XX:CMSFullGCsBeforeCompaction

设定进行多少次CMS垃圾回收后,进行一次内存压缩。

-XX:+CMSClassUnloadingEnabled

允许对类元数据区进行回收。

-XX:CMSInitiatingPermOccupancyFraction

当永久区占用率达到这一百分比时,启动CMS回收(前提是-XX:+CMSClassUnloadingEnabled激活了)。

-XX:CMSInitiatingPermOccupancyOnly

表示只在到达阈值的时候才进行CMS回收。

-XX:+CMSIncrementalMode

使用增量模式,比较适合单CPU。增量模式在JDK8中标记为废弃,并且将在JDK9中彻底移除。

4、 G1收集器相关的参数

-XX:+UseG1GC

使用G1回收器。

-XX:MaxGCPauseMillis

设置最大垃圾收集停顿时间。

-XX:GCPauseIntervalMillis

设置停顿间隔时间。

深入JVM虚拟机(四) Java GC收集器相关推荐

  1. JVM总结(四)GC收集器以及JDK7,JDK8中JVM内存变化

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来. GC收集器 如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存 ...

  2. Java GC收集器配置说明

    根据Java GC收集器具体分类,我们可以看出JVM根据需求不同提供了三种选择:串行收集器.并行收集器.并发收集器. 串行收集器只适用于小数据量的情况,我们主要了解一下并行收集器和并发收集器.默认情况 ...

  3. jvm系列二之GC收集器

    目录 参考 概念理解 并发和并行 吞吐量 GC垃圾收集器 Serial New收集器 Parallel New(并行)收集器 Parallel Scavenge(并行)收集器 Serial Old(串 ...

  4. 深入理解java虚拟机gc_jvm GC收集器与内存分配(深入理解java虚拟机第三章)

    jvm GC收集器与内存分配(深入理解java虚拟机第三章) 本篇是<深入理解java虚拟机第三章>的笔记记录. 一 为什么要关注GC和内存分配? 需要排查各种内存溢出.内存泄漏问题时,或 ...

  5. JVM的GC回收算法、GC收集器以及内存分配策略

    目录 •写在前面 •标记-清除算法 •复制算法 •标记-整理算法 •HotSpot上的算法实现保障 •GC收集器 •内存分配策略 •写在前面 JVM的垃圾回收算法.收集器以及内存分配策略放在一起了解和 ...

  6. Jvm 系列(五):Java GC 分析

    Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...

  7. 后台开发人员面试内容——JVM虚拟机(四)

    一.Java类加载机制 类从被加载到虚拟机内存中开始,到卸载出内存,它的整个生命周期包括:加载(Loading).验证(Verification).准备(Preparation).解析(Resolut ...

  8. jvm系列(五):Java GC 分析

    Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...

  9. 研究了 2 天,终于知道 JDK 8 默认 GC 收集器了!

    JDK 8 到底默认用的是哪款 GC 收集器? 为啥是 JDK8?不是 9 也不是 10?因为 JDK8 还是市场占有率最高的,所以针对这个版本我做了深入的探索. <深入理解 Java 虚拟机& ...

最新文章

  1. 涉密计算机格式化维修,涉密计算机中的涉密信息被删除或格式化后,不可复原,可以连接互联网 - 作业在线问答...
  2. 为何大多数人做出来的图表只是一坨屎?
  3. 我国将于今年春季发射空间站核心舱 空间站进入全面实施阶段
  4. 使用Opencv的一些注意事项
  5. bilibili Saber 实时计算平台架构与实践【Apache Flink 替换 Spark Stream的架构与实践】
  6. python qt信号在qml 的使用_QML与Python通信
  7. 这个免费的交互式课程在一小时内学习JavaScript
  8. 运用Loadrunner测试Mysql数据库性能
  9. 动易自定义标签HTML输出,动易标签【ArticleList】
  10. 204. 电子编程入门到工程师--混沌与秩序--天书信号
  11. 小程序/CSS的text-decoration属性
  12. 共享单车信息系统服务器部署,共享单车云服务器搭建
  13. 一款 Windows 上的万能工具 Wox
  14. 大学英语专业开计算机课程吗,加拿大留学,温莎大学英语计算机专业了解一下!...
  15. 拟一维喷管流动的数值解——亚声速-超声速等熵喷管流动的守恒型CFD解法(MacCormack方法)
  16. 暗影精灵5风扇怎么调_惠普暗影精灵5内部结构是怎么样的 他的散热效果好不好呢...
  17. 获取微信公众号的二维码图片
  18. 数据加速器 GooseFS 1.3.0 版本正式发布
  19. Debian个人使用入门
  20. 我的HackerOne漏洞赏金平台漏洞挖掘流程

热门文章

  1. 用计算机探索 按一定规律排列,探索规律练习题1
  2. python定义一个_Python,包括定义一个类
  3. maskrcnn还可以加网络吗_绿茶加蜂蜜的功效,绿茶可以加蜂蜜吗?
  4. [汇编语言]常用命令
  5. Stack(栈 c++模版实现)
  6. android 5.0状态栏下载地址,Android沉浸式状态栏(5.0以上系统)
  7. 交通标志识别项目教程
  8. matlab如何使用cu文件,Matlab编译cuda的.cu文件
  9. 7-11 堆栈操作合法性 (20 分)以及堆栈讲解(c语言实现)
  10. 天梯赛 喊山 bfs