【Java】图解 JVM 垃圾回收(二):垃圾收集器、Full GC

图解 JVM 垃圾回收(二)

  • 1.垃圾收集器
    • 1.1 内存分配与回收策略
    • 1.2 Serial 收集器
    • 1.3 Parallel Scavenge 收集器
    • 1.4 ParNew 收集器
    • 1.5 CMS 收集器
    • 1.6 G1 收集器
  • 2.Full GC 的触发条件

1.垃圾收集器

Java 虚拟机提供了多种垃圾回收器,每种回收器有其特定的用途和优势。以下是常见的垃圾回收器:

在这里插入图片描述
连线表示垃圾收集器可以配合使用。

  • 单线程与多线程:单线程指的是垃圾收集器只使用一个线程进行收集,而多线程使用多个线程。
  • 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并行指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。

1.1 内存分配与回收策略

JVM 在进行 GC 时,并非每次都对堆内存(新生代、老年代;方法区)区域一起回收的,大部分时候回收的都是指新生代

针对 HotSpot VM 的实现,它里面的 GC 按照回收区域又分为两大类:部分收集Partial GC),整堆收集Full GC)。

  • 部分收集:不是完整收集整个 Java 堆的垃圾收集。其中又分为:
    • 新生代收集Minor GC / Young GC):只是新生代的垃圾收集。
    • 老年代收集Major GC / Old GC):只是老年代的垃圾收集。目前,只有 CMS GC 会有单独收集老年代的行为。很多时候 Major GC 会和 Full GC 混合使用,需要具体分辨是老年代回收还是整堆回收。
    • 混合收集Mixed GC):收集整个新生代以及部分老年代的垃圾收集。目前只有 G1 GC 会有这种行为。
  • 整堆收集:收集整个 Java 堆和方法区的垃圾。

1.2 Serial 收集器

  • -XX:+UseSerialGC
  • -XX:+UseSerialOldGC

Serial 是一个单线程收集器了。它的 “单线程” 的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程( “Stop The World” ),直到它收集结束。

在这里插入图片描述

  • Serial 收集器由于没有线程交互的开销,自然可以获得很高的单线程收集效率。
  • Serial Old 收集器是 Serial 收集器的老年代版本,它同样是一个单线程收集器。它主要有两大用途:一种用途是在 JDK 1.5 以及以前的版本中与 Parallel Scavenge 收集器搭配使用,另一种用途是作为 CMS 收集器的后备方案。
  • 新生代采用 复制 算法,老年代采用 标记-整理 算法。

1.3 Parallel Scavenge 收集器

  • -XX:+UseParallelGC(新生代)
  • -XX:+UseParallelOldGC(老年代)

Parallel 收集器其实就是 Serial 收集器的 多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器类似。默认的收集线程数CPU 核数 相同,当然也可以用参数(-XX:ParallelGCThreads)指定收集线程数,但是一般不推荐修改。

Parallel Scavenge 收集器关注点是 吞吐量(高效率的利用 CPU)。CMS 等垃圾收集器的关注点更多的是用户线程的 停顿时间(提高用户体验)。所谓吞吐量就是 CPU 中用于运行用户代码的时间与 CPU 总消耗时间的比值。Parallel Scavenge 收集器提供了很多参数供用户找到最合适的停顿时间或最大吞吐量,如果对于收集器运作不太了解的话,可以选择把内存管理优化交给虚拟机去完成也是一个不错的选择。

新生代采用 复制 算法,老年代采用 标记-整理 算法。

Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本。使用 多线程标记-整理 算法。在注重吞吐量以及 CPU 资源的场合,都可以优先考虑 Parallel Scavenge 收集器和 Parallel Old 收集器(JDK 8 默认的新生代和老年代收集器)。

1.4 ParNew 收集器

  • -XX:+UseParNewGC(新生代)

ParNew 收集器其实跟 Parallel 收集器很类似,区别主要在于它可以和 CMS 收集器配合使用。

新生代采用 复制 算法。

1.5 CMS 收集器

  • -XX:+UseConcMarkSweepGC(老年代)

CMS(Concurrent Mark Sweep),Mark Sweep 指的是 标记-清除 算法。

CMS 收集器是一种以获取 最短回收停顿时间 为目标的收集器。它非常符合在注重用户体验的应用上使用,它是 HotSpot 虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作

它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程分为四个步骤:

  • 初始标记: 暂停所有的其他线程(STW),并记录下 GC Roots 直接能引用的对象,速度很快。
  • 并发标记: 并发标记阶段就是从 GC Roots 的直接关联对象开始遍历整个对象图的过程, 这个过程耗时较长但是不需要停顿用户线程, 可以与垃圾收集线程一起并发运行。因为用户程序继续运行,可能会有导致已经标记过的对象状态发生改变。
  • 重新标记: 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录(主要是处理漏标问题),这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。主要用到三色标记里的增量更新算法做重新标记。
  • 并发清理: 开启用户线程,同时 GC 线程开始对未标记的区域做清扫。这个阶段如果有新增对象会被标记为黑色不做任何处理。
  • 并发重置:重置本次 GC 过程中的标记数据。

在这里插入图片描述

CMS 主要优点:并发收集、低停顿。但是它有下面几个明显的缺点:

  • ⭕ 对 CPU 资源敏感(会和服务抢资源)。
  • ⭕ 无法处理浮动垃圾(在并发标记和并发清理阶段又产生垃圾,这种浮动垃圾只能等到下一次 GC 再清理了)。
  • ⭕ 它使用的 “标记-清除” 回收算法会导致收集结束时会有大量空间碎片产生,通过参数 -XX:+UseCMSCompactAtFullCollection 可以让 JVM 在执行完标记清除后再做整理,往往出现老年代空间剩余,但无法找到足够大连续空间来分配当前对象,不得不提前触发一次 Full GC。
  • ⭕ 执行过程中的不确定性,会存在上一次垃圾回收还没执行完,然后垃圾回收又被触发的情况,特别是在并发标记和并发清理阶段会出现,一边回收,系统一边运行,也许没回收完就再次触发 Full GC,也就是 “Concurrent Mode Failure”,此时会进入 “Stop The World”,用 Serial Old 垃圾收集器来回收。

1.6 G1 收集器

G1(Garbage-First)是一款面向服务端应用的垃圾收集器,在多 CPU 和大内存的场景下有很好的性能。

堆被分为新生代和老年代,其它收集器进行收集的范围都是整个新生代或者老年代,而 G1 可以直接对新生代和老年代一起回收。G1 把堆划分成多个大小相等的 独立区域Region),新生代和老年代不再物理隔离。
在这里插入图片描述
通过引入 Region 的概念,从而将原来的一整块内存空间划分成多个的小空间,使得每个小空间可以单独进行垃圾回收。这种划分方法带来了很大的灵活性,使得可预测的停顿时间模型成为可能。通过记录每个 Region 垃圾回收时间以及回收所获得的空间(这两个值是通过过去回收的经验获得),并维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的 Region。

每个 Region 都有一个 Remembered Set,用来记录该 Region 对象的引用对象所在的 Region。通过使用 Remembered Set,在做可达性分析的时候就可以避免全堆扫描。

G1 收集器的运作大致可划分为以下几个步骤:

  • 初始标记Initial Marking):仅仅只是标记一下 GC Roots 能直接关联到的对象。
  • 并发标记Concurrent Marking):从 GC Roots 开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。
  • 最终标记Final Marking):对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的 SATB(Snapshot At The Beginning,原始快照)记录。
  • 筛选回收Live Data Counting and Evacuation):负责更新 Region 的统计数据,对各个 Region 的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个 Region 构成回收集,然后把决定回收的那一部分 Region 的存活对象复制到空的 Region 中,再清理掉整个旧 Region 的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多条收集器线程并行完成的。

它具备以下特点:

  • 并行与并发:G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPU(CPU 或者 CPU 核心)来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 Java 程序继续执行。
  • 分代收集:虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但是还是保留了分代的概念。
  • 空间整合:与 CMS 的 “标记-清除” 算法不同,G1 从整体来看是基于 “标记-整理” 算法实现的收集器;从局部上来看是基于 “标记-复制” 算法实现的。
  • 可预测的停顿:这是 G1 相对于 CMS 的另一个大优势,降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 N 毫秒。

在这里插入图片描述
G1 收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的 Region(这也就是它的名字 Garbage-First 的由来)。这种使用 Region 划分内存空间以及有优先级的区域回收方式,保证了 G1 收集器在有限时间内可以尽可能高的收集效率(把内存化整为零)。

从 JDK 9 开始,G1 垃圾收集器成为了默认的垃圾收集器

2.Full GC 的触发条件

对于 Minor GC,其触发条件非常简单,当 Eden 空间满时,就将触发一次 Minor GC。而 Full GC 则相对复杂,有以下条件:

  • 调用 System.gc() 只是建议虚拟机执行 Full GC,但是虚拟机不一定真正去执行。不建议使用这种方式,而是让虚拟机管理内存。
  • 老年代空间不足。老年代空间不足的常见场景为前文所讲的:大对象直接进入老年代、长期存活的对象进入老年代等。为了避免以上原因引起的 Full GC,应当尽量不要创建过大的对象以及数组。除此之外,可以通过 -Xmn 虚拟机参数调大新生代的大小,让对象尽量在新生代被回收掉,不进入老年代。还可以通过 -XX:MaxTenuringThreshold 调大对象进入老年代的年龄,让对象在新生代多存活一段时间。
  • 空间分配担保失败。使用复制算法的 Minor GC 需要老年代的内存空间作担保,如果担保失败会执行一次 Full GC。
  • JDK 1.7 及以前的永久代空间不足(1.7 之后元空间不足)。在 JDK 1.7 及以前,HotSpot 虚拟机中的方法区是用永久代实现的,永久代中存放的为一些 Class 的信息、常量、静态变量等数据。当系统中要加载的类、反射的类和调用的方法较多时,永久代可能会被占满,在未配置为采用 CMS GC 的情况下也会执行 Full GC。如果经过 Full GC 仍然回收不了,那么虚拟机会抛出 java.lang.OutOfMemoryError。为避免以上原因引起的 Full GC,可采用的方法为增大永久代空间或转为使用 CMS GC。
  • Concurrent Mode Failure。执行 CMS GC 的过程中同时有对象要放入老年代,而此时老年代空间不足(可能是 GC 过程中浮动垃圾过多导致暂时性的空间不足),便会报 Concurrent Mode Failure 错误,并触发 Full GC。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/479030.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

运维:自主编码实现运维自动化的转型之旅

引言 随着业务系统和底层中间件服务的复杂度不断增加,传统手工运维方式面临着诸多挑战和限制。人工编写运维脚本显得非常低效,同时手动执行运维操作存在着巨大风险。在此情况下,推动运维自动化成为运维人员必须落地实施的工作。运维同学如果…

机器学习基础(一)理解机器学习的本质

导读:在本文中,将深入探索机器学习的根本原理,包括基本概念、分类及如何通过构建预测模型来应用这些理论。 目录 机器学习 机器学习概念 相关概念 机器学习根本:模型 数据的语言:特征与标签 训练与测试&#xf…

2023年全球前端大技术大会(GMTC北京站2023):核心内容与学习收获(附大会核心PPT下载)

此次峰会是一次内容丰富、有深度和广度的技术盛会。参会者不仅可以了解前端技术的最新发展和未来趋势,还可以与业界专家交流心得,提升自己的技能和能力。同时,此次大会也促进了全球前端社区的交流和合作,推动了前端技术的创新和发…

字节跳动推出颠覆性文生视频模型,可自由控制动作!

在Sora引爆文生视频赛道之前,国内的字节跳动也推出了一款创新性视频模型——Boximator。 与Gen-2、Pink1.0等模型不同的是,Boximator可以通过文本精准控制生成视频中人物或物体的动作。 例如,下雨天,大风把一位女生的雨伞吹走了…

毕业设计:基于知识图谱的《红楼梦》人物关系可视化

文章目录 项目介绍部署步骤项目运行 项目介绍 github地址:https://github.com/chizhu/KGQA_HLM?tabreadme-ov-file 基于知识图谱的《红楼梦》人物关系可视化:应该是重庆邮电大学林智敏同学的毕业设计,在学习知识图谱的过程中参考使用。 文…

Cadence Allegro PCB设计88问解析(三十三) 之 Allegro 中 Quick Reports的使用

一个学习信号完整性仿真的layout工程师 在进行PCB设计时,经常会查看一下整个PCB的基本信息,比如器件个数,网络数量、pin的数量。尤其在投板的时候还要查看下Dangling Lines、Dangling Vias等。还有其他的关于shape、via、走线、钻孔等等相关信…

LabVIEW风力机智能叶片控制系统

​LabVIEW风力机智能叶片控制系统 介绍了一种风力机智能叶片控制系统的开发。通过利用LabVIEW软件与CDS技术,该系统能够实时监测并调整风力机叶片的角度,优化风能转换效率。此项技术不仅提高了风力发电的稳定性和效率,而且为风力机的智能化管…

解决问题的七个步骤,你知道吗?

在日常生活和工作中,我们时常会面临各种问题和挑战。有效地解决问题不仅能帮助我们顺利前行,还能提升我们的个人能力和价值。如何更有效地解决问题? 案例背景: 一家电商公司的项目经理,负责一个即将上线的促销活动。…

SICTF Round#3 Web方向 题解WP

100%_upload 题目描述:小茂夫说:一直上传恶意文件尊嘟要生气了,世事莫固守,转变思路求突破 开题,注意有个文件包含 题目把后缀过滤死了,无法上传php后缀文件。文件内容些许过滤,短…

每日学习总结20240219

每日总结 20240219 1.文件类型.csv CSV文件是一种以逗号分隔值(Comma-Separated Values)为标记的文本文件,它可以用来存储表格数据。每一行表示一条记录,而每一条记录中的字段则使用逗号或其他特定的分隔符进行分隔。 常用场景…

SpringMVC基础复习-概念+mvc配置类中代码+异常处理

SpringMVC将Servlet的一些通用功能进行了抽取和封装,代码由两部分组成:前端控制器(由SpringMVC提供,主要负责:接收参数返回数据)处理器(调用业务层代码),核心依赖spring-webmvc(springboot中自动配置,用spring-boot-starter-web) 在项目中添加web环境的初始类和核心配置类,其中…

计算机视觉学习指南(划分为20个大类)

计算机视觉的知识领域广泛而庞杂,涵盖了众多重要的方向和技术。为了更好地组织这些知识,我们需要遵循无交叉无重复(Mutually Exclusive Collectively Exhaustive,MECE)的原则,并采用循序渐进的方式进行分类…