《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中常用的垃圾回收器. ...
随机推荐
- Django集成腾讯COS对象存储
前言 最近遇到一个场景需要把大量的资源文件存储到 OSS 里,这里选的是腾讯的 COS 对象存储 (话说我接下来想搞的 SnapMix 项目也是需要大量存储的,我打算搭个 MinIO 把 24T 的服 ...
- 技术如何通过API接口获取自己想要同款商品的数据
确定数据源: 首先,你需要确定哪些平台或服务提供商提供了你感兴趣的商品数据.例如,电商平台.品牌商.市场调研公司等. 了解API文档: 访问提供商的开发者门户网站,阅读API文档.文档会详细介绍如何使 ...
- AArch64 汇编学习笔记
PIE(Position Independent Executable,位置无关的可执行文件)通过随机化可执行文件各个部分在虚拟内存中的地址使得攻击者无法通过预测地址进行恶意行为. 汇编开发工具: a ...
- SNAT 与 DNAT
本文为博主原创,转载请注明出处: SNAT(Source Network Address Translation,源网络地址转换)和DNAT(Destination Network Address T ...
- PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
大家好,我是码农先森. 我们在某宝或某多多上抢购商品时,如果只是下了订单但没有进行实际的支付,那在订单页面会有一个支付倒计时,要是过了这个时间点那么订单便会自动取消.在这样的业务场景中,一般情况下就会 ...
- 【转】 Vue中import from的来源:省略后缀与加载文件夹
原文地址 Vue中import from的来源:省略后缀与加载文件夹_超频化石鱼的博客-CSDN博客 ,原文地址排版格式可能更好,建议看原文,本文只是为了转载记录 Vue使用import ... fr ...
- 使用 Dependify 工具探索 .NET 应用程序依赖项
在大型项目中,由于各种组件的复杂性和互连性,管理依赖项可能变得具有挑战性.如果没有适当的工具或文档,可能很难浏览项目并对依赖项做出假设.以下是在大型项目中难以导航项目依赖项的几个原因: 复杂性:大型项 ...
- ARC119F 题解
前言 ARC119F 好厉害,是没见过的自动机 DP. 正文 [1] 分析 主要分析一下为什么这么写. [2] 状态设计 [3] 自动机状态转移 感觉状态设计中最难的就是如何处理带 \(O\) 的. ...
- EF Core – QueryFilter & Interception
主要参考 Global Query Filters Interceptors QueryFilter QueryFilter 就是默认过滤, 非常适合用来做 Soft Delete builder.H ...
- Autodesk Maya无法打开 refrence file 解决办法
删除预设 预设的位置在: 我的文档/maya/version/ prefs 备注: 我的文档/maya/version/ 无法确定是不是该路径下的所有文件夹都能删除,所以只剪切了 prefs 文件夹出 ...