乐趣区

关于java:深入理解JVM七JVM的垃圾收集器介绍配置和选型

0. 前言

1.Serial 垃圾收集器

1.1Serial 垃圾收集器优缺点及实用场景

1.2Serial 垃圾收集器的开启和应用

2.ParNew 垃圾收集器

2.1ParNew 垃圾收集器优缺点及实用场景

2.2ParNew 垃圾收集器的开启和应用

3.Parallel 垃圾收集器

3.1Parallel 垃圾收集器优缺点及实用场景

3.2Parallel 垃圾收集器的开启和应用

4.CMS 垃圾收集器

4.1CMS 垃圾收集器优缺点及实用场景

4.2CMS 垃圾收集器的开启和应用

4.3CMS 垃圾收集器的应用注意事项

5.G1 垃圾收集器

5.1G1 垃圾收集器优缺点及实用场景

5.2G1 垃圾收集器的开启和应用

6. 垃圾收集器的算法汇总

0. 前言
咱们之前在深刻了解 JVM(五)——垃圾收集算法中介绍过各种垃圾收集的算法,然而 GC 算法是内存回收的实践,垃圾收集器是算法的落地实现。首先到目前为止并没有完满的垃圾收集器, 咱们只有针对适合的场景,采纳适当的垃圾收集器

1.Serial 垃圾收集器
Serial 垃圾收集器是最根本,倒退最悠久的单线程垃圾收集器。咱们先来看一下它的垃圾收集过程图。

执行流程:假如咱们的 java 过程的堆内存曾经被耗尽,当 Serial 垃圾收集器启动的时候,它会进行所有用户线程,达到一个 STOP-THE-WORLD(会有较长的进展)的状态,等到垃圾收集结束之后,再运行用户线程进行工作。

串行收集器是最古老,最稳固且效率最高的收集器,只应用一个垃圾收集器去回收会在其收集的时候产生较长的进展,尽管要暂停所有其它的线程,然而它最简略高效,对于限定单个 CPU 环境来说,没有线程交互的开销能够取得最高的单线程垃圾收集效率。

1.1Serial 垃圾收集器优缺点及实用场景
长处:实现简略,稳固,单线程效率最高
毛病:会有较长时间的进展,用户体验差
实用场景:单 CPU 或小内存,较小的程序

1.2Serial 垃圾收集器的开启和应用
-XX:+UseSerialGC 开启 Serial 垃圾收集器
-XX:+PrintCommandLineFlags 启动服务的时候,查看程序应用的默认 JVM 参数

开启上述参数后,会应用 Serial(Young 区)+Serial(Old 区)的组合。
新生代采纳复制算法,老年代采纳标记整顿算法。

当咱们把上述参数输出 IDEA 之后,在启动服务的第一行,就会呈现咱们曾经开启了 Serial 垃圾收集器。

2.ParNew 垃圾收集器
ParNew 垃圾收集器其实就是 多线程版本的 Serial 垃圾收集器,其余的行为和 Serial 垃圾收集器截然不同,ParNew 收集器在垃圾收集过程中同样也须要暂停所有工作线程(STOP-THE-WORLD)。


2.1ParNew 垃圾收集器优缺点及实用场景
长处:实现简略,稳固,在多 cpu 的状况下,比单线程效率更高,进展工夫短
毛病:也会有肯定的进展,用户体验差
实用场景:多 CPU,谋求进展工夫,须要疾速响应的场景,如互联网利用

2.2ParNew 垃圾收集器的开启和应用
-XX:+UseParNewGC 开启 ParNew 垃圾收集器
-XX:+PrintCommandLineFlags 启动服务的时候,查看程序应用的默认 JVM 参数

开启上述参数后,会应用 ParNew(Young 区)+Serial(Old 区)的组合。新生代采纳复制算法,老年代采纳标记整顿算法。

3.Parallel 垃圾收集器

Parallel 垃圾收集器相似于 ParNew 垃圾收集器,也是一个新生代的垃圾收集器,应用复制算法,也是一个并行的多线程垃圾收集器,不 过它的关注点是达到可管制的吞吐量
(吞吐量:cpu 用于运行用户代码的工夫和 cpu 耗费的总工夫的比值)
(吞吐量公式:用户代码的工夫 / (用户代码的工夫)+(垃圾回收的占用工夫))

比方程序运行 100 分钟,垃圾收集器运行 1 分钟,吞吐量就是 99%。

3.1Parallel 垃圾收集器优缺点及实用场景
长处:多线程收集速度快,能够管制吞吐量
毛病:如果参数设置地过于小,线程之间一直切换意味着须要额定的开销,从而垃圾回收和用户线程的总工夫将会缩短。
应用场景:多 CPU,须要大吞吐量,如后盾计算利用

3.2Parallel 垃圾收集器的开启和应用
-XX:+UseParallelGC 开启 Parallel 垃圾收集器
-XX:+PrintCommandLineFlags 启动服务的时候,查看程序应用的默认 JVM 参数


因为 parallel 垃圾收集器是管制吞吐量的,所以还有几个重要的参数。

-XX:+UseAdaptiveSizePolicy 设置 Parallel Scavenge 收集器具备自适应调节策略。
在这种模式下,年老代的大小、Eden 和 Survivor 的比例、降职老年代的对象年龄等参数会被主动调整,已达到在堆大小、吞吐量和进展工夫之间的平衡点。

在手动调优比拟艰难的场合,能够间接应用这种自适应的形式,仅指定虚拟机的最大堆、指标的吞吐量(GCTimeRatio)和进展工夫(MaxGCPauseMIllis),让虚拟机本人实现调优工作。

-XX:ParallelGCThreads 设置年老代并行收集器的线程数。个别的最好与 CPU 数量相等,以防止过多的线程数影响垃圾回收性能。88
默认状况下,当 CPU 数量小于 8 个,ParallelGCThreads 的值等于 CPU 数量。
当 CPU 数量大于 8 个时,线程数为 3 +((5*CPU_Count)/8)。

-XX:MaxGCPauseMillis 设置垃圾收集器最大进展工夫(即 STW 的工夫)。单位是毫秒。
为了尽可能地把进展工夫管制在 MaxGCPauseMillis 以内,收集器在工作时会调整 Java 堆大小或者其余一些参数。

对于用户来讲,进展工夫越短体验越好。然而在服务器端,咱们重视高并发,整体的吞吐量。所以服务器端适宜 Parallel,进行管制。

该参数审慎应用。

-XX:GCTimeRatio:取值范畴(0,100)垃圾收集工夫占总工夫的比例(=1 / (N + 1))用于掂量吞吐量的大小。默认值 99,也就是垃圾回收工夫不超过 1%。
MaxGCPauseMIllis 越大,这个比例就越高。

4.CMS 垃圾收集器
CMS(Concurrent Mark Sweep: 并发标记革除) 是一种以最短回收进展工夫为指标的收集器。它的垃圾收集线程和用户线程一起执行,将 STW 的工夫达到最短,采纳标记 - 革除算法。

咱们从图能够看出,cms 垃圾收集器一共分四个步骤:
初始标记 :须要 stop the world,应用可达性剖析算法标记,速度很快
并发标记 :多个线程同时并发标记
从新标记 :修改并发标记期间因为用户程序持续运作而导致的变动
并发革除:并发进行革除

4.1CMS 垃圾收集器优缺点及实用场景
长处:并发收集,低进展
毛病:对 cpu 资源敏感,无奈解决浮动垃圾,基于标记革除,会产生碎片
实用场景:实用于堆内存大,CPU 核数多的服务器端利用,这类利用及其器重服务器响应速度,心愿零碎进展工夫最短。

4.2CMS 垃圾收集器的开启和应用
-XX:+UseConcMarkSweepGC 开启 CMS 垃圾收集器
-XX:+PrintCommandLineFlags 启动服务的时候,查看程序应用的默认 JVM 参数

4.3CMS 垃圾收集器的应用注意事项
1. 因为并发执行,CMS 在收集与利用线程同时执行的时候,会减少堆内存的占用。也就是说,CMS 垃圾收集器要在老年代堆内存用尽之前实现垃圾回收,否则 CMS 垃圾收集器回收失败, 会触发担保机制,串行老年代收集器将会以 STWGC 的形式进行一次 GC,造成大量进展工夫。

2. 标记革除算法无奈整顿碎片,老年代会随着工夫的流逝而用尽内存,最初不得不通过担保机制对堆内存进行压缩。CMS 也提供了参数 -XX:CMSFullGCsBeForeCompation 来指定多少次 CMS 垃圾收集之后,进行一次压缩 GC。

5.G1 垃圾收集器
在介绍 G1 收集器之前,咱们先总结一下以前的垃圾收集器的共同点,再来看 G1。
年老代和老年代是各自独立且间断的内存块。
年老代收集应用 eden+S0+S1 进行复制算法。
老年代收集器必须扫描整个老年代区域
都是以尽可能少而疾速地执行 GC 为设计准则。

这时,咱们来看 G1:
G1 利用在多处理器和大容量内存环境中,在实现高吞吐量的同时,尽可能地满足垃圾收集器暂停工夫的要求。另外,它还具备以下个性:

像 CMS 垃圾收集器一样,能与工作线程同时并发执行。
整顿空间速度更快。
不心愿就义大量的吞吐性能。
不须要更大的 JAVA Heap。

G1 垃圾收集器的初衷是为了取代 CMS 垃圾收集器,它同 CMS 相比,在以下方面体现更杰出。
G1 是一个采纳标记 - 整顿算法,不会产生很多内存碎片
G1 能 充分利用多 CPU 硬件劣势,缩短 STW 工夫
宏观上G1 不辨别新生代和老年代,把内存划分成了多个独立的子区域。能够看做围棋的棋盘图。
G1 收集器外面的整个内存区域都混合在一起了,但其自身依然在小范畴内仍要进行年老代和老年代的辨别。
G1 尽管也是分代收集器,但整个内存分区不在物理上进行隔离,每个区域会随着对象的变动进行老年代和新生代之间的转化。

G1 大略就把内存分成了如图所示

各个区域也由原来的产生了变动:

针对 Eden 区域进行收集,Eden 区耗尽后会被触发,次要是小区域收集 + 造成间断的内存块,防止内存碎片
假如 Eden 区域内存不够,局部对象降职到 Survivor 区域,如果 Survivor 区域不够,字节进入老年代。

执行过程 :和 CMS 一样
初始标记 :须要 stop the world,应用可达性剖析算法标记,速度很快
并发标记 :多个线程同时并发标记
从新标记 :修改并发标记期间因为用户程序持续运作而导致的变动
并发革除:并发进行革除

5.1G1 垃圾收集器优缺点及实用场景
长处:
G1 不会产生内存碎片
G1 效率高
G1 能够准确管制进展
毛病:
G1 须要记忆集 (具体来说是卡表)来记录新生代和老年代之间的援用关系,这种数据结构在 G1 中须要占用大量的内存,可能达到整个堆内存容量的 20% 甚至更多。而且 G1 中保护记忆集的老本较高,带来了更高的执行负载,影响效率。

5.2G1 垃圾收集器的开启和应用
-XX:+UseG1GC 开启 G1 收集器
-XX:+PrintCommandLineFlags 启动服务的时候,查看程序应用的默认 JVM 参数

另外 G1 还有以下辅助参数。

-XX:G1HeapRegionSize=n: 设置 G1 区域的大小,值是 2 的次数幂,范畴是 1MB~32MB

-XX:MaxGCPauseMillis GC 最大进展工夫,单位是毫秒

-XX:InitiatingHeapOccupancyPercent:堆占用了多少个的时候就触发 GC,默认为 45

-XX:ParallelGCThreads STW 期间,并行 GC 线程数

-XX:G1ReservePercent 默认 10%。也就是老年代会预留 10% 的空间来给新生代的对象降职. 设置闲暇的空间预留内存百分比,以升高 OOM 的危险。

6 垃圾收集器的算法汇总

参数 新生代垃圾收集器 新生代算法 老年代垃圾收集器 老年代算法
-XX:+UserSerialGC SerialGC 复制 SerialOldGC 标记整顿
-XX:+UseParNewGC ParNew 复制 SerialOldGC 标记整顿
-XX:+UseParallelGC Parallel 复制 ParallelOld 标记整顿
-XX:+UseConcMarkSweepGC ParNew 复制 CMS+SerialOld 标记革除
-XX:+UseG1GC G1 整体上采纳标记 - 整顿算法 部分是复制算法,不会产生碎片

总结:
明天咱们介绍了各种垃圾收集器的特点,收集过程,收集算法和应用场景,心愿咱们能多多应用,把握垃圾收集器。

退出移动版