《JVM第9课》垃圾回收器
先来看一张图,串行代表两个垃圾回收器按顺序执行,并行代表同时执行。STW代表工作线程暂停,Stop The World的意思。
| 垃圾回收器 | 执行顺序 | 执行方式 | 作用区域 | 使用算法 | 说明 |
|---|---|---|---|---|---|
| Serial GC | 串行 | 工作线程暂停,单线程进行垃圾回收 | 新生代 | 复制算法 | |
| Serial Old GC | 串行 | 工作线程暂停,单线程进行垃圾回收 | 老年代 | 标记-整理算法 | |
| ParNew GC | 并行 | 工作线程暂停,多线程进行垃圾回收 | 新生代 | 复制算法 | Serial GC的多线程版 |
| CMS GC | 并行 | 用户线程和垃圾回收线程同时执行 | 老年代 | 标记-清除算法 | 低暂停 |
| Parallel GC | 并行 | 工作线程暂停,多线程进行垃圾回收 | 新生代 | 复制算法 | 和ParNew相比能动态调整内存分配情况JDK8默认 |
| Parallel Old GC | 并行 | 工作线程暂停,多线程进行垃圾回收 | 老年代 | 标记整理算法 | 替代串行的Serial Old GC |
| G1 | 并行 | 用户线程和垃圾回收线程同时执行 | 整堆 | 分区算法 | 在延迟可控的情况下尽可能提高吞吐量JDK9默认 |
| ZGC | 并行 | 用户线程和垃圾回收线程同时执行 | 整堆 | 分页算法 | STW的时间不超过1ms,且不会随着堆的大小增加而增加 |
常用命令:
-XX:+PrintCommandLineFlags,查看使用的垃圾收集器
-XX:+UseSerialGC,指定使用Serial GC处理新生代,并且默认会使用Serial Old GC处理老年代
-XX:+UseParNewGC,指定新生代使用ParNew GC,-XX:+UseConcMarkSweepGC,指定老年代使用CMS GC
-XX:+UseParallelGC,指定新生代使用Parallel GC,-XX:+UserParallelOldGC,指定老年代使用Parallel Old GC,这两个配置一个,另一个自动激活
1. Serial GC、Serial Old GC
Serial GC和Serial Old GC是比较早的垃圾回收器,那个时候一般的服务器CPU还只有一核,所以一个线程进行垃圾回收就够了。串行的意思就是两个垃圾回收器不能同时执行。
2. Parallel GC、Parallel Old GC
Parallel GC进行垃圾回收时也会暂停用户线程(STW),与Serial GC的不同就是它时多线程进行垃圾回收的。下面画个图方便理解垃圾回收过程。
在一次垃圾回收过程中,会进行一次STW,并且会有多个线程同时进行垃圾回收,回收完后用户线程回复运行。
3. CMS GC
CMS全称是ConcMarkSweep,即并发标记清除。但是它不是某个JDK默认的,要使用的话就加上-XX:+UseConcMarkSweepGC参数。
CMS GC是Java9之前我们很常用的垃圾回收器,是针对老年代的使用标记-清除算法的垃圾回收器。我们一般会使用CMS GC替代默认的老年代垃圾回收器,因为CMS GC的特点是低暂停。实现低暂停的方法是在初始标记阶段只标记GC Roots直接可达的对象,这个阶段比较短,所以对用户线程来说是低暂停。
下面用一张图展示它的垃圾回收过程:
阶段一,初始标记:
- STW,暂停所有用户线程。
- 然后标记GC Roots直接可达的对象,就是第一层对象。
- 一旦标记完就恢复用户线程继续执行。
- 这个阶段很快。
阶段二,并发标记:
- 从上一个阶段标记出的对象,开始遍历整个老年代,标记出所有的可达对象。
- 耗时虽然比较长,但好在不需要STW,可与用户线程一起执行。
- 采用的是三色标记算法(大家自行拓展)。
阶段三,重新标记:
- 由于在并发标记阶段,应用程序线程也在运行,可能会导致一些对象的状态发生变化,例如新的对象被创建或旧的对象被删除。
- 为了修正这些问题,需要进行一次短暂的停顿,重新检查并更新标记状态
- 这个阶段也是“Stop-The-World”的,但也不会太长。
阶段四,并发清理:
- 清除垃圾对象,释放空间供后续分配使用。
- 清理工作与应用程序线程并发进行,不会引起停顿。
阶段五,并发重置:
- CMS收集器会准备下一次垃圾回收循环,重置内部数据结构等。
- 这一阶段也是与应用程序并发进行的。
CMS整个垃圾回收过程更长了,但是STW的时间变短了,而且在垃圾回收过程中大部分时间用户线程可以执行,所以用户体验更好了。
在并发清理过程中,可能用户线程会产生新的垃圾,这些就是“浮动垃圾”,只能等到下一次GC时来清理。
如果在并发标记、并发清理过程中,用户线程产生的新对象要进入老年代,但是老年代空间又不够,那么就会导致“concurrent mode failure”,此时就会利用Serial Old来做一次垃圾回收,就会做一次全局STW。
由于采用的是标记-清除算法,所以会产生内存碎片,可以通过参数 -XX:+UseCMSCompactAtFullCollection 让JVM在执行完标记-清除后再做一次整理,也可以通过 -XX:CMSFullGCsBeforeCompaction 来指定多少次GC后来做整理,默认是0,表示每次GC后都整理。
CMS垃圾回收器能够在大多数时间内与应用程序并发执行,减少了因垃圾回收引起的停顿时间。然而,CMS也有一些缺点,比如它可能产生大量的浮动垃圾(floating garbage),并且在某些情况下仍然会导致较长的停顿。随着Java版本的发展,G1 GC和ZGC等更先进的垃圾回收器逐渐取代了CMS的地位。
4. G1(Garbage-First)
G1垃圾回收器是在 Java 7 update4 之后引入,并在Java 9中成为默认的垃圾收集器的。G1的设计目标是提供高吞吐量的同时,实现可预测的暂停时间,特别适合处理大堆内存的应用场景。下面介绍一些G1垃圾回收器的内存结构。
先看张图:
之前我们讲的垃圾回收器把堆内存分为Eden、S0、S1、老年代这四个区域,每个区域都是连续的。而在G1中,整块堆内存被分成2048个大小相等的region,这些region在物理上不要求是连续的,但在逻辑上是连续的。每个region可以独立地作为Eden、Survivor或老年代的一部分。所以说G1还是把内存分为了Eden、Survivor、老年代区,只不过空间可以是不连续的了。
Humongous区是专门用来存放大对象的(如果一个对象大小超过了一个region的50%,那么就是大对象)
用一张图展示垃圾回收过程:
阶段一,初始标记:
- 短暂的STW。
- 标记出直接可达对象。
阶段二,并发标记:
- 并发遍历整个堆,标记所有可达对象。
- 不需要STW。
- 三色标记。
阶段三,最终标记:
- 这也是一个较短的STW。
- 修正并发标记期间由于应用程序运行而可能产生的误差。
阶段四,筛选回收:
- 需要STW,来清除垃圾对象。
- 可通过 -XX:MaxGCPauseMillis 来指定GC的STW停顿的时间,所以可能并不会回收掉所有的垃圾对象,默认为200ms(略小于人的平均反应速度)。
- 由于回收时间有限,所有会选择更有回收价值(垃圾更多)的区域进行回收。这也是Garbage-First(垃圾优先)的名字由来。
- 采用的是复制算法,不会产生碎片(会把某个region里的可达对象移动到空白的region里)。
由于筛选回收阶段的STW时间可能不够用导致垃圾约积越多,为了避免OOM,G1 中还提供了另外三种垃圾回收模式:Young GC、Mixed GC 和 Full GC,它们有各自的触发条件。
Young GC: Eden区满,就会触发G1的YoungGC,对Eden区进行垃圾回收。
Mixed GC: 老年代的占用率达到了 -XX:InitiatingHeapOccupancyPercent 指定的百分比,回收所有的新生代以及部分老年代,以及大对象区。
Full GC: 在进行Mixed GC的过程中,采用的是复制算法,如果没有空的region可用,就会触发Full GC,会STW,并采用单线程来进行标记-整理算法进行GC,相当于一次Serial GC。
《JVM第9课》垃圾回收器的更多相关文章
- 深入理解JVM(五)——垃圾回收器
轻松学习JVM(五)——垃圾回收器 上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某一种算法进行垃圾回收,而是将不同的垃圾回收算法包装在不同的垃圾回收器当中, ...
- [JVM 相关] Java 新型垃圾回收器(Garbage First,G1)
回顾传统垃圾回收器 HotSpot 垃圾收集器实现 Serial Collector(串型收集器) 使用场景,大多数服务器是单核CPU. 适用收集场景:1. 新生代收集(Young Generatio ...
- 深入理解JVM虚拟机3:垃圾回收器详解
JVM GC基本原理与GC算法 Java的内存分配与回收全部由JVM垃圾回收进程自动完成.与C语言不同,Java开发者不需要自己编写代码实现垃圾回收.这是Java深受大家欢迎的众多特性之一,能够帮助程 ...
- JVM学习第二天(垃圾回收器和内存分配策略)大章
说道垃圾回收器大家应该都会有所了解,GC白,当然说道具体的可能就不是很清楚了,今天我们就来玩一玩; GC要做的事情: 第一步:确定堆中需要回收的对象; 第二步:什么时候回收; 第三步:怎样回收 为什么 ...
- JVM——垃圾收集算法及垃圾回收器
一.垃圾回收算法 1.标记-清除算法 1)工作流程 算法分为"标记"和"清除"阶段:首先标记出所有需要回收的对象(标记阶段),在标记完成后统一回收所有被标记的对 ...
- JVM学习总结三——垃圾回收器
整两天再看调优分析的部分,发现实际运行环境下,还是要考虑配置垃圾回收器,所以这里就加一小章介绍一下. 首先来看一下HotSpot所支持回收期的关系图: 图中可以看到一共有7中垃圾回收器,以中间绿线为界 ...
- JVM(五)垃圾回收器的前世今生
全文共 2195 个字,读完大约需要 8 分钟. 如果垃圾回收的算法属于内存回收的方法论的话,那本文讨论的垃圾回收器就属于内存回收的具体实现. 因为不同的厂商(IBM.Oracle),实现的垃圾回收器 ...
- jvm默认的并行垃圾回收器和G1垃圾回收器性能对比
http://www.importnew.com/13827.html 参数如下: JAVA_OPTS="-server -Xms1024m -Xmx1024m -Xss256k -XX:M ...
- Hotspot JVM垃圾回收器
前两篇<JVM入门——运行时数据区><JVM常见垃圾回收算法>所提到的实际上JVM规范以及常用的垃圾回收算法,具体的JVM实现实际上不止一种,有JRockit.J9等待,当然最 ...
- java虚拟机入门(五)- 常见垃圾回收器及jvm实现
上节讲完了垃圾回收的基础,包括java的垃圾是什么,如何寻找以及常用的垃圾回收算法,那么那么多的理论知识讲完了,具体是什么样的东西在做着回收垃圾的事情呢?我们接下来就好好聊聊jvm中常用的垃圾回收器. ...
随机推荐
- 智能指针相关:enable_shared_from_this()在开发中的常见应用
类中使用shared_ptr()的问题 当我们先定义一个指针,然后再用这个指针构造两个智能指针 int main() { int* pt = new int(); std::shared_ptr< ...
- MySQL数据库基本操作包括MySQL过程、MySQL声明
MySQL数据库 操纵数据库 查看数据库 show databases; 创建数据库 create database <database_name>; 删除数据库 drop databas ...
- 为什么说 Swoole 是 PHP 程序员技术水平的分水岭?
大家好,我是码农先森. 谈到这个话题有些朋友心中不免会有疑惑,为什么是 Swoole 而不是其他呢?因为 Swoole 是基于 C/C++ 语言开发的高性能异步通信扩展,覆盖的特性足够的多,有利于 P ...
- ThinkPHP 6 + PHP7.4.3nts +nginx 使用mysql和oracle数据库
ThinkPHP 6 + PHP7.4.3nts +nginx 使用mysql和oracle数据库. 前言 业务需求,之前使用的php 7.3.4nts ,mysql自己写的代码,需要对接第三方系统, ...
- Mac 打开软件提示‘“xxx”已损坏,无法打开。您应该将它移到废纸篓。’解决方法
产生错误的原因是软件没有签名.使用下面的命令给软件签名就好了. sudo xattr -rd com.apple.quarantine /Applications/xxx.app
- 自制 ShareLaTeX 镜像
Overleaf 官方的 sharelatex 镜像的 TeX Live 版本可能较旧,无法安装最新的宏包,并且往往只包含了少量的基础宏包.为了方便使用,我们可以自己构建一个使用最新 TeX Live ...
- maven 打包 pom build
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframew ...
- WPF 实现一个吃豆豆的Loading加载动画
运行的效果如下 先引入一下我们需要的库 在nuget上面搜一下"expression.Drawing",安装一下这个包 我们再创建一个Window,引入一下这个包的命名空间 我们设 ...
- Identity – Options
前言 上一篇已经有写到一些配置了, 但不完整, 这里专门写一篇吧. 防暴力登入 services.Configure<IdentityOptions>(options => { // ...
- Java 8 新特性:Stream 流快速入门
前言 在 java 中,涉及到对数组.集合等集合类元素的操作时,通常我们使用的是循环的方式进行逐个遍历处理,或者使用 stream 流的方式进行处理. 什么是 Stream? Stream(流)是一个 ...