Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 垃圾收集器

news2024/12/28 22:13:18

文章目录

    • 垃圾回收机制
    • Stop-the-World
    • 垃圾收集器
      • 垃圾收集器分类
      • Serial 收集器
      • Serial Old 收集器
      • ParNew 收集器
      • Parallel Scavenge 收集器
      • Parallel Old 收集器
      • CMS 收集器
        • CMS 收集器缺点
      • G1 收集器
        • G1 收集器特点
        • G1 收集器的分代理念
        • G1 收集器运作过程

垃圾回收机制

垃圾回收Garbage Collection,GC),顾名思义就是释放垃圾占用的空间,当需要排查各种内存溢出问题、当垃圾收集成为系统达到更高并发的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。有效的使用可以使用的内存,对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收

Stop-the-World

"Stop The World"是 Java 垃圾收集中的一个重要概念。在垃圾收集过程中,JVM 会暂停所有的用户线程,这种暂停被称为"Stop The World"事件。这么做的主要原因是为了防止在垃圾收集过程中,用户线程修改了堆中的对象,导致垃圾收集器无法准确地收集垃圾。

"Stop The World"事件会对 Java 应用的性能产生影响。如果停顿时间过长,就会导致应用的响应时间变长,对于对实时性要求较高的应用,如交易系统、游戏服务器等,这种情况是不能接受的。

因此,在选择和调优垃圾收集器时,需要考虑其停顿时间。Java 中的一些垃圾收集器,如 G1ZGC(下文有详细讲解),都会尽可能地减少了"Stop The World"的时间,通过并发的垃圾收集,提高应用的响应性能。

垃圾收集器

如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。Java 垃圾收集器(Garbage Collector, GC)是 Java 虚拟机(JVM)的一部分,它自动管理内存,回收不再使用的对象所占用的内存空间。这有助于防止内存泄漏,并且使得开发人员可以更专注于业务逻辑的编写而不是内存管理。

没有万能的垃圾收集器,只有根据具体应用场景选择适合自己的垃圾收集器。垃圾收集器是垃圾回收算法(如引用计数法、标记清除法、标记整理法、复制算法等)的具体实现。它的主要任务是识别并回收那些不再被程序使用的对象所占用的内存空间,从而避免内存泄漏和内存溢出的问题。

垃圾收集器分类

就目前来说,JVM 的垃圾收集器主要分为两大类:分代收集器分区收集器,分代收集器的代表是 CMS,分区收集器的代表是 G1ZGC

JDK 默认垃圾收集器(使用 java -XX:+PrintCommandLineFlags -version 命令查看):

  • JDK 8:Parallel Scavenge(新生代)+ Parallel Old(老年代)
  • JDK 9 ~ JDK20: G1

在这里插入图片描述

Serial 收集器

Serial(串行)收集器是最基本、历史最悠久的垃圾收集器。此收集器是一个单线程收集器了。

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

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

Serial 收集器

Serial 收集器简单而高效(与其他收集器的单线程相比)。由于没有线程交互的开销,自然可以获得很高的单线程收集效率,对于运行在 Client 模式下的虚拟机来说是个不错的选择

Serial Old 收集器

Serial 收集器的老年代版本,它同样是一个单线程收集器。它主要有两大用途:一种用途是在 JDK1.5 以及以前的版本中与 Parallel Scavenge 收集器搭配使用,另一种用途是作为 CMS 收集器的后备方案。

![[Pasted image 20231011233428.png]]

ParNew 收集器

ParNew 收集器是 Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。

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

![[Pasted image 20231011233540.png]]

并行和并发概念补充

  • 并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。

  • 并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行,可能会交替执行),用户程序在继续运行,而垃圾收集器运行在另一个 CPU 上。

Parallel Scavenge 收集器

Parallel Scavenge 收集器也是多线程收集器 ,其关注点是吞吐量(高效率的利用 CPU)。

是 JDK1.8 的默认收集器,可以使用
java -XX:+PrintCommandLineFlags -version 命令查看

吞吐量(Throughput)就是 CPU 中用于运行用户代码的时间与 CPU 总消耗时间的比值

Parallel Scavenge 收集器提供了很多参数供用户找到最合适的停顿时间或最大吞吐量,如果对于收集器运作不太了解,手工优化存在困难的时候,使用 此收集器配合自适应调节策略,把内存管理优化交给虚拟机去完成也是一个不错的选择。

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

Parallel Old收集器运行示意图

Parallel Old 收集器

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

![[Pasted image 20231011234122.png]]

CMS 收集器

CMS(Concurrent Mark Sweep)收集器 是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用。

CMS(Concurrent Mark Sweep)收集器是 HotSpot 虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作

从名字中的 Mark Sweep 这两个词可以看出,CMS 收集器是由 标记-清除 算法实现的。它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程分为四个步骤:

  1. 初始标记: 暂停所有的其他线程,并记录下直接与 root 相连的对象,速度很快

  2. 并发标记: 同时开启 GC 和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象。
    因为用户线程可能会不断的更新引用域,所以 GC 线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方

  3. 重新标记: 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短

  4. 并发清除: 开启用户线程,同时 GC 线程开始对未标记的区域做清扫。

CMS 收集器

这是一款优秀的垃圾收集器:并发收集、低停顿。但是它有下面三个明显的缺点:

CMS 收集器缺点
  1. 对 CPU 资源非常敏感,因此在 CPU 资源紧张的情况下,CMS 的性能会大打折扣。默认情况下,CMS 启用的垃圾回收线程数是(CPU数量 + 3)/4,当 CPU 数量很大时,启用的垃圾回收线程数占比就越小。但如果 CPU 数量很小,例如只有 2 个 CPU,垃圾回收线程占用就达到了 50%,这极大地降低系统的吞吐量,无法接受。

  2. CMS 采用的是「标记-清除」算法,会产生大量的内存碎片,导致空间不连续,当出现大对象无法找到连续的内存空间时,就会触发一次 Full GC,这会导致系统的停顿时间变长。

  3. CMS 无法处理浮动垃圾,当 CMS 在进行垃圾回收的时候,应用程序还在不断地产生垃圾,这些垃圾会在 CMS 垃圾回收结束之后产生,这些垃圾就是浮动垃圾,CMS 无法处理这些浮动垃圾,只能在下一次 GC 时清理掉。

G1 收集器

G1 (Garbage-First) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器,以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征。引入了基于区域(Region)的垃圾回收策略。它是从 JDK 1.7 版本开始引入的。

G1垃圾收集器的主要目标是实现更短的停顿时间和更高的吞吐量。

G1 收集器特点

被视为 JDK1.7 中 HotSpot 虚拟机的一个重要进化特征,在 JDK 9 时取代 CMS 成为了默认的垃圾收集器。它具备以下特点:

  • 增量G1 可以以增量方式执行垃圾回收,这意味着它不需要一次性回收整个堆空间,而是可以逐步、增量地清理。有助于控制停顿时间,尤其是在处理大型堆时。

  • 并行与并发G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPU(CPU 或者 CPU 核心)来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 java 程序继续执行。

  • 分代收集:虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但是还是保留了分代的概念。

  • 空间整合:与 CMS 的“标记-清除”算法不同,G1 从整体来看是基于“标记-整理”算法实现的收集器;从局部上来看是基于“标记-复制”算法实现的。

  • 可预测的停顿:这是 G1 相对于 CMS 的另一个大优势,降低停顿时间是 G1CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 N 毫秒。

G1 收集器的分代理念

G1 是基于分代的思想进行设计的。它将堆内存分为多个大小相等的区域(Region),每个区域都可以是 Eden 区、Survivor 区或者 Old 区。

在这里插入图片描述

可以通过 -XX:G1HeapRegionSize=n 来设置 Region 的大小,可以设定为 1M、2M、4M、8M、16M、32M(不能超过)。

G1 有专门分配大对象的 RegionHumongous 区,而不是让大对象直接进入老年代的 Region 中。在 G1 中,大对象的判定规则就是一个大对象超过了一个 Region 大小的 50%,比如每个 Region 是 2M,只要一个对象超过了 1M,就会被放入 Humongous 中,而且一个大对象如果太大,可能会横跨多个 Region 来存放。

G1 收集器运作过程

它的设计思想是将堆内存划分为多个大小相等的区域(Region),每个区域都可以是EdenSurvivorOld 区域。G1垃圾收集器通过并发、增量和并行的方式,以区域为粒度进行垃圾回收,其工作过程如下:

  1. 初始标记(Initial Mark):G1垃圾收集器会首先标记出GC Roots能直接关联到的对象,并记录下这些对象的存活状态。在此阶段,应用程序的执行会停顿下来。

  2. 并发标记(Concurrent Marking):G1垃圾收集器并发进行标记工作,在应用程序运行的同时,标记剩余的存活对象。在这个阶段,G1会进行跨区域的引用扫描,标记存活对象。

  3. 最终标记(Final Mark):在并发标记阶段结束后,G1会做一次最终标记来修正并发标记期间有可能发生的引用变化。该阶段的停顿时间会较短。

  4. 筛选回收(Live Data Counting):G1根据各个区域内的垃圾量和存活对象数量等信息,选择最有价值的区域进行垃圾收集。这个阶段被称为G1的"Garbage-First"策略。

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

  1. 并发清理(Concurrent Cleanup):G1进行并发的垃圾清理工作,在应用程序运行的同时,回收垃圾区域中的无用对象

![[Pasted image 20231011235136.png]]

G1垃圾收集器在整个垃圾回收过程中,会控制垃圾回收的停顿时间,尽量减少对应用程序的影响。它可以根据应用程序的需要动态调整各个阶段的时间比例,以达到更好的性能和吞吐量

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二、Servlet

文章目录 1. Servlet技术1.1 什么是Servlet1.2 手动实现 Servlet 程序1.3 url 地址到 Servlet 程序的访问1.4 Servlet 的生命周期1.5 GET 和 POST 请求的分发1.6 通过继承 HttpServlet 实现 Servlet 程序1.7 使用 IDEA 创建 Servlet 程序1.8 Servlet 类的继承体系 2. ServletCo…

计算机人工智能前沿进展-大语言模型方向-2024-09-13

计算机人工智能前沿进展-大语言模型方向-2024-09-13 1. OneEdit: A Neural-Symbolic Collaboratively Knowledge Editing System Authors: Ningyu Zhang, Zekun Xi, Yujie Luo, Peng Wang, Bozhong Tian, Yunzhi Yao, Jintian Zhang, Shumin Deng, Mengshu Sun, Lei Liang, Z…

有机水果蔬菜检测系统源码分享

有机水果蔬菜检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

NPM如何切换淘宝镜像进行加速

什么是淘宝镜像NPM? 淘宝镜像NPM和官方NPM的主要区别在于服务器的地理位置和网络访问速度。淘宝镜像NPM是由淘宝团队维护的一个npm镜像源,主要服务于中国大陆用户,提供了一个国内的npm镜像源,地址为 https://registry.npmmirror.…

MySQL 事件调度器用法解析

MySQL 事件调度器用法解析 在日常的数据库运维与开发实践中,自动化执行任务是一项至关重要的需求,它极大地提升了数据库管理的效率和准确性。这些任务可能包括清理不再需要的历史数据以释放存储空间、更新汇总或统计信息以保持数据的新鲜度,…

Java-数据结构-二叉树-习题(三)  ̄へ ̄

文本目录: ❄️一、习题一(前序遍历非递归): ▶ 思路: ▶ 代码: ❄️二、习题二(中序遍历非递归): ▶ 思路: ▶ 代码: ❄️三、习题三(后序遍历非递归): ▶ 思路: …

2025年最新大数据毕业设计选题-基于Spark分析相关

选题思路 回忆学过的知识(Python、Java、Hadoop、Hive、Sqoop、Spark、算法等等。。。) 结合学过的知识确定大的方向 a. 确定技术方向,比如基于Hadoop、基于Hive、基于Spark 等等。。。 b. 确定业务方向,比如民宿分析、电商行为分析、天气分析等等。。。…

[网络层]-IP协议相关特性

IP协议 基本概念 主机 : 配有IP地址,但是不进行路由控制的设备路由器 : 既配有IP地址,又能进行路由控制节点: 主机和路由器的统称 协议头格式 4位版本(version):占四位,用于指定IP协议的版本,例如,使用IPv4,该字段就为44位首部长度: 表示IP协议首部的长度,以32位bit (4字节)…

秋招突击——9/10、9\11——算法练习——携程笔试练习——2024年秋招第一批笔试

文章目录 引言笔试准备2024年秋招研发第一批第一题第二题第二次实现 第三题第四题第五题参考实现 总结 引言 准备全力冲携程,好好做算法,去线下面试!今天就好好做做携程往年的笔试! 笔试准备 2024年秋招研发第一批 第一题 imp…

<<编码>> 第 14 章 反馈与触发器(1)--振荡器 示例电路

继电器振荡器 info::操作说明 无需操作, 保持控制开关常闭以形成振荡 如需停止振荡, 则断开控制开关 注: 要看到灯闪烁的效果, 右上角 “仿真速度” 控制杆应设置为一个较低的位置(靠左侧) 另: 因继电器内部开关跳动动画效果耗时太长, 即便设置为较低的仿真速度也无法观察到开关…

有效的对嵌入式操作系统进行消毒处理

这篇论文的标题是《Effectively Sanitizing Embedded Operating Systems》,作者是 Jianzhong Liu, Yuheng Shen, Yiru Xu, Hao Sun, Heyuan Shi, Yu Jiang。论文主要研究了嵌入式操作系统的安全性问题,并提出了一种名为 EmbSan 的嵌入式系统消毒器&#…

计算机的错误计算(九十六)

摘要 探讨 的计算精度问题。 计算机的错误计算(五十五)与(七十八)分别列出了 IEEE 754-2019 中的一些函数与运算。下面再截图给出其另外3个运算。 例1. 已知 x-0.9999999999966 . 计算 不妨在Python下计算,则有&am…

TI DSP TMS320F280025 Note11:F280025时钟系统

TMS320F280025 F280025时钟系统 ` 文章目录 TMS320F280025 F280025时钟系统TMS32F280025时钟系统框图**时钟系统框图分析**时钟源主内部振荡器(INTOSC2)用内部振荡器(INTOSC1)派生的时钟振荡器时钟(OSCCLK)系统锁相环输出时钟(PLLRAWCLK)设备时钟域系统时钟(PLLSYSCLK)CPU时钟(…

PyTorch 激活函数及非线性变换详解

激活函数是深度学习模型的重要组成部分,它们引入非线性,从而使模型能够更好地拟合复杂的数据模式。本文将详细介绍激活函数的作用、常见类型、经典应用示例,并比较它们的优缺点。 激活函数的作用 激活函数的主要作用是引入非线性变换&#…

12 Java文件处理之写入、读取:IO流(中):高级流(缓冲流、转换流、序列化流和反序列化流、打印流)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、缓冲流1 字节缓冲流(1)BufferedInputStream:字节缓冲输入流构造方法---- BufferedInputStream(InputStream in):创建一个使用默认缓冲区大小的缓冲输入流。---- BufferedInputStream(In…

算法题目复习(0909-0917)

1. 连续子序列和 pdd的算法题&#xff0c;根本不记得怎么做 给一个数组&#xff0c;有正数和负数&#xff0c;算出连续子序列的和最大为多少 int maxSubArraySum(vector<int>& nums) {int maxSoFar nums[0];int maxEndingHere nums[0];for (size_t i 1; i <…

说说几款耳机

从前&#xff0c;大约在戴森推出他们那款奇特的发明——戴森耳机与空气净化器组合一年后&#xff0c;人们仍对这个奇怪的产品感到困惑。这款穿戴式空气净化耳机更像是一个实验&#xff0c;缺乏实际用途。回想起那时的评测&#xff0c;大家一致认为这是有史以来最无意义的产品之…

IDEA 2024.3 EAP新特征早览!

0 前言 IntelliJ IDEA 2024.3 第一个 EAP 版本已发布&#xff0c;提前体验 下一个重大版本的一部分改进。 持续关注 EAP 更新&#xff0c;未来几周内将推出更多 IntelliJ IDEA 新功能。尝试这些新功能&#xff0c;分享您的反馈&#xff0c;共同完善 IDE。 1 AI 助手 1.1 内…

Web3入门指南:从基础概念到实际应用

Web3&#xff0c;即“去中心化的第三代互联网”&#xff0c;正在逐步改变我们对互联网的传统认知。从最初的静态网页&#xff08;Web1.0&#xff09;到互动平台和社交媒体为主的互联网&#xff08;Web2.0&#xff09;&#xff0c;Web3的目标是让用户重新掌握对数据和数字资产的…

比特币10年价格数据(2014-2024)分析(基础)

数据入口&#xff1a;【每周挑战】比特币10年价格数据可视化和量化分析 - Heywhale.com 本数据集包含 2014 - 2024 的比特币美元价格数据&#xff0c;具体包含比特币每日的开盘价、最高价、最低价、收盘价以及成交量等关键信息。数据说明如下&#xff1a; 字段说明Date日期&a…