【JVM】垃圾回收:垃圾收集器

news2025/8/12 18:30:07

一、语境中的并行与并发

并行

并行描述的时多条垃圾收集器线程之间的关系,说明同一时间有多条这样的线程在协同工作,通常默认此时用户线程是处于等待状态。

并发

并发描述的是垃圾收集器线程与用户线程之间的关系,说明同一时间垃圾收集器线程与用户线程都在运行。由于用户线程并未被冻结,所以程序仍然能响应服务请求,但由于垃圾收集器线程占用了一部分系统资源,此时应用程序的处理的吞吐量将受到一定影响。

二、串行收集器

  • 单线程: Serial 收集器(年轻代) + Serial Old 收集器(老年代)
  • 客户端模式的最好选择:适合个人电脑(适合CPU核数少的,多了也没用)、堆内存较小

在这里插入图片描述

三、吞吐量优先收集器

  • 多线程并行:Parallel Scavenge 收集器(年轻代) + Parallel Old 收集器(老年代)。jdk8默认使用
  • 吞吐量 = 运行用户代码时间 /(运行用户代码时间+运行垃圾收集时间【次数*单次时间,次数越多,时间越长】)
  • 适合堆内存较大,多核 cpu
  • 目标:尽可能让 单次GC的时间 最短。即单位时间内,STW的时间最短

在这里插入图片描述

四、响应时间优先收集器

  • 多线程并发:ParNew 收集器(年轻代) + CMS(Concurrent Mark Sweep)收集器(老年代)
  • 适合堆内存较大,多核 cpu
  • 目标:尽可能让 单次STW的时间 最短
  • 问题:
    1. “标记清除算法”:导致空间碎片化,无法存储大对象,进而导致”并发失败“。临时启用 SerialOld 收集器进行标记整理
    2. “并发标记、并发清理”:产生 “浮动垃圾”,需要预留空间。
    3. “重新标记”:先做新生代回收再重新扫描,减轻压力

在这里插入图片描述

五、G1收集器

JDK9 开始成为服务端模式下的默认垃圾收集器,CMS被声明为不推荐使用

  • 定义:Garbage First ,jdk9默认使用。

    • 2004 论文发布
    • 2009 JDK 6u14 体验
    • 2012 JDK 7u4 官方支持
    • 2017 JDK 9 默认
  • 适用场景

    • 用于老年代
    • 同时注重吞吐量(Throughput)和低延迟(Low latency),默认的暂停目标是 200 ms
    • 超大堆内存,会将堆划分为多个大小相等的 Region
    • 整体上是 标记+整理 算法,两个区域之间是 复制 算法。意味着G1运行期间不会产生内存空间碎片
  • 相关 JVM 参数

    • -XX:+UseG1GC :使用G1收集器
    • -XX:G1HeapRegionSize=size:设置堆内存每个区域大小
    • -XX:MaxGCPauseMillis=time:设置回收时最长停止时间

1)回收阶段

在这里插入图片描述

2)Young Collection

  • 将新对象分配到各个伊甸园区域

在这里插入图片描述

  • 当堆中伊甸园区域被逐渐被占满后,触发 Young Collection 并 STW 和 进行初始标记。将伊甸园区域幸存的对象使用复制的算法拷贝到幸存区域

在这里插入图片描述

  • 当堆中伊甸园区域被逐渐被占满、幸存区域中对象超过阈值后,触发 Young Collection 并 STW 和 进行初始标记。将伊甸园区域幸存的对象使用复制的算法拷贝到幸存区域,将幸存区域中没有超过阈值的对象拷贝到另一个幸存区域,将幸存区域中超过阈值的对象晋升到老年代区域

在这里插入图片描述

3)Young Collection + 并发标记

  • Young Collection:在 Young GC 时会进行 GC Root 的初始标记

  • 并发标记:老年代区域占用堆空间比例达到阈值时,进行 并发标记(不会 STW),由下面的 JVM 参数决定

    -XX:InitiatingHeapOccupancyPercent=percent (默认45%)

在这里插入图片描述

4)Mixed Collection

会对 E、S、O 进行全面垃圾回收

  • 最终标记(Remark)会 STW

  • 拷贝存活(Evacuation)会 STW会选择回收价值最高(获得的空间大小、回收所需时间)的区域进行回收,以满足暂停时间的设置

    -XX:MaxGCPauseMillis=ms

在这里插入图片描述

5)写屏障

在虚拟机层面对 “引用类型字段赋值” 这个动作的AOP切面。也就是说在赋值的前后增加相应代码执行额外的动作

  • 写后屏障:解决跨代引用问题,维护记忆集
  • 写前屏障:解决并发标记阶段的引用变更问题,并发扫描时的原始快照

6)跨代引用

新生代回收的跨代引用(老年代引用新生代)问题

  • 记忆集(Remembered Set)卡表(记忆集的实现)

  • 在引用变更时,更新脏卡:通过 post-write barrier**(写后屏障)** + dirty card queue

    • 异步更新:concurrent refinement threads 更新 Remembered Set

在这里插入图片描述

7)重新标记-Remark

pre-write barrier (写前屏障) + satb_mark_queue

  • 删除引用(原始快照):白色的C对象灰色的B对象 所引用,但在处理前被用户线程删除了灰色B对象的引用。
    • 异步更新:此时C对象 删除引用操作前的写前屏障将C对象加入到一个队列中,并将其标记为灰色
  • 插入引用:用户线程让 黑色的A对象 引用 白色的C对象
  • 重新标记阶段:STW,将队列中的对象取出并进行重新检测

在这里插入图片描述

8)DK8u20字符串去重

  • -XX:+UseStringDeduplication
  • 优点:节省大量内存
  • 缺点:略微多占用了 cpu 时间,新生代回收时间略微增加
String s1 = new String("hello"); // char[]{'h','e','l','l','o'}
String s2 = new String("hello"); // char[]{'h','e','l','l','o'}
  • 将所有新分配的字符串放入一个队列。当新生代回收时,G1并发检查是否有字符串重复,如果它们值一样,让它们引用同一个 char[]
  • 注意,与 String.intern() 不一样
    • String.intern() 关注的是字符串对象
    • 而字符串去重关注的是 char[]
    • 在 JVM 内部,使用了不同的字符串表

9)DK8u40并发标记类卸载

  • -XX:+ClassUnloadingWithConcurrentMark: 默认启用

  • 所有对象都经过并发标记后,就能知道哪些类不再被使用

  • 卸载条件:当一个类加载器的所有类都不再使用,则卸载它所加载的所有类

10)DK8u60回收巨型对象

  • 一个对象大于 region 的一半时,称之为巨型对象
  • G1 不会对巨型对象进行拷贝,回收时被优先考虑
  • G1 会跟踪老年代所有 incoming 引用,这样老年代 incoming 引用为0 的巨型对象就可以在新生代垃圾回收时处理掉

11)DK9并发标记起始时间的调整

  • 并发标记必须在堆空间占满前完成,否则退化为 FullGC
  • JDK 9 前:需要使用 -XX:InitiatingHeapOccupancyPercent
  • JDK 9 时:可以动态调整
    • -XX:InitiatingHeapOccupancyPercent 用来设置初始值
    • 进行数据采样并动态调整,总会添加一个安全的空档空间

12)DK9更高效的回收

  • 250+增强
  • 180+bug修复
  • https://docs.oracle.com/en/java/javase/12/gctuning

六、💡GC总结

  • SerialGC

    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足发生的垃圾收集 - full gc
  • ParallelGC

    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足发生的垃圾收集 - full gc
  • CMS

    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存不足发生的垃圾收集 - major gc
    • 并发清除失败导致老年代内存不足 - full gc
  • G1

    • 新生代内存不足发生的垃圾收集 - minor gc
    • 老年代内存达到一定比例 - mixed gc
    • 混合收集失败导致老年代内存不足 - full gc(多线程)

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

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

相关文章

简单实现一个虚拟形象系统

前言 上周启动居家开会的时候,看到有人通过「虚拟形象」功能,给自己带上了口罩、眼镜之类,于是想到了是不是也可以搞一个简单的虚拟形象系统。 大致想来,分为以下几个部分: 卷积神经网络(CNN) 下面讲解一下三层CN…

视频格式转换器哪个好用?万兴优转-好用的视频格式转换器

视频格式转换器是用于转换视频格式的软件,是指用于视频转换、音频转换、CD轨抓取、音视频混合转换、音视频剪切、连接转换、视频水印叠加、滚动字幕、个性化文字、图片叠加、视频相框叠加的音视频转换工具。 也就是说,视频有非常多的格式如AVI、VCD、SVC…

【JavaWeb从零到一】会话技术CookieSessionJSP

🚀【JavaWeb从零到一】系列文章目录 🚩【JavaWeb从零到一】前置知识 🚩【JavaWeb从零到一】Mysql基础总结 🚩【JavaWeb从零到一】JDBC详解 🚩【JavaWeb从零到一】JDBC连接池&JDBCTemplate Cookie&Session&…

王学岗音视频开发(二)—————OpenGLES开发实践

矩阵以及矩阵运算 上图就是m x a 的矩阵 1x30x22x1 :为左侧第一行乘以右侧第一列。 1x10x12x0 :为左侧第一行乘以右侧第二列。 -1x33x21x1:为左侧第二行乘以右侧第一列。 -1x13x11x0:为左侧第二行乘以右侧第二列。 矩阵的行列式 伴随矩阵 A*表示伴随矩阵 OpenGL 教程----屏…

Grails SpringBoot国际化不生效

问题描述: grails项目使用了国际化,按照官方文档的说法: 会根据用户浏览器访问时使用的Accept-Language头自动选择合适的语言。 但无论浏览器了配置什么语言甚至配置了Tomcat启动参数 -Duser.languagexxx -Duser.regionxxx页面显示依旧是英…

[附源码]java毕业设计一点到家小区微帮服务系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

QPushButton按钮用法

QPushButton 简介 QPushButton是一个很常用的一个按钮控件,主要用于创建一个可按压的按键。它显示了一 个文本和一个图标。另外,你也可以在创建时,指定一个快捷键。 基本用法 1. 创建 QPushButton主要有两种创建方法,一种是直…

SQLite实现的学生管理系统

SQLite数据库 案例资源所在地址: https://download.csdn.net/download/weixin_41957626/87150608?spm1001.2014.3001.5503 1.简介 1.1引入 1.前面学习的文件存储和SharedPreference存储的方式只能存储一些小型的数据但是对于复杂关系以及复杂数据结构的数据仅仅靠…

交互与前端16 Tabulator 表格实践4

说明 继续给表格来加一些小功能。 内容 1 分页 在表格初始化的地方加两行配置,表格就实现了分页 pagination:true, //enable.paginationSize:20, // this option can take any positive integer value2 超链接 这个需求的来源是,一些微服务需要注释,所以我写了很多文档…

科研教育「双目视觉技术」首选!维视MV-VS220双目立体视觉系统开发平台

NO.1产品背景 在最近大热的自动驾驶赛道,大疆采用新的技术路线——双目立体视觉。具体来说,它就是模拟人的视觉系统,通过两个临近摄像头所拍摄到的画面的视差,来还原出三维立体结构。不需要对海量数据进行标注和训练,可…

Echarts 散点象限图(二)动态绘制

之前发布过一篇文章Echarts散点象限图,基于死数据来绘制的,但实际开放场景中,需要请求数据,而且可能会动态更改数据,这时候需要如何处理,有什么要注意的地方,这篇文章详细说明一下。 主要需要处理的地方就是四个象限的markArea,需要根据中心的位置来画,你可以想象成…

36 - 经典问题解析三(赋值 string)

---- 整理自狄泰软件唐佐林老师课程 1. 关于赋值的疑问 什么时候需要重载赋值操作符?编译器是否提供默认的赋值操作? 编译器为每个类 默认重载了赋值操作符默认的赋值操作符 仅完成 浅拷贝当需要进行 深拷贝 时 必须重载赋值操作符赋值操作符与拷贝构造…

Elasticsearch系列【1】概述

有道无术,术尚可求,有术无道,止于术。 文章目录Elastic公司Elastic StackElasticsearch结构化/非结构化数据全文搜索ES 发展史ES 特点ES 应用场景ES 应用案例Beats 系列LogstashKibanaElastic公司 Elastic是一家以搜索引擎闻名世界的软件公司…

pythoin爬虫2之利用cookie进行登录

python爬虫2之利用cookie进行登录利用requests模拟post方法cookies的获取session综合实例拓展:实现时间间隔(第一次抓取后间隔...秒进行下一次抓取)利用requests模拟post方法 requests.post(url,data,hearders) url即要解析的网址data即是向服…

【学习笔记18】JavaScript对象的基本认识

一、什么是对象 (一)概念 😃 就是一个数据的集合(复杂数据)😁 对象属于复杂数据类型(引用数据类型) (二)知识点的补充 JS 的数据类型 1. 基本数据 2. 复杂数据(引用数据类型) 引用数…

图像处理技术:数字图像分割 ------ 图像分割、边界分割(边缘检测)、区域分割

一、图像分割概述 • 定义 是指根据灰度、彩色、空间纹理、几何形状等特征把图像划分 成若干个互不相交的区域,使得这些特征在同一区域内表现出一致 性或相似性,而在不同区域间表现出明显的不同 分割出来的区域应该同时满足: (1&#xff09…

opencv之修改尺寸、灰度转换(python)

1、修改图片大小 #修改图片大小 resize_img cv.resize(img,dsize(200,100)) 完整代码 import cv2 as cv img cv.imread("C:\\Users\\Administrator\\Desktop\\huge.jpg") #修改图片大小 resize_img cv.resize(img,dsize(200,100)) #显示修改后图片 cv.imshow(修改…

【单目标优化求解】贪婪非分级灰狼算法求解单目标优化问题(G-NHGWO)【含Matlab源码 2005期】

⛄一、贪婪随机自适应搜索算法简介 1 贪婪随机自适应搜索算法 GRASP算法分两个阶段,构造阶段和局部搜索阶段[3]。在构造阶段,初始化可行解S和候选集C,并对候选集的每一个元素进行评估,判断是否可加入限制候选列表(Res…

西电通信技术基础实验

实验一 基带传输常用编码 实验内容 数字编码技术:AMI码、曼彻斯特编码、HDB3码 实验目的 掌握几种基带传输常用码型的编码规则,如AMI码、HDB3码、曼彻斯特码。然后利用MATLAB设计并实现它们的编码。 实验环境 MATLAB程序设计、MATLAB Simulink仿真…

IMX6ULL + SPI LCD(驱动IC ILI9341)显示简单的QT界面

1. 硬件: 使用正点原子的IMX6ULL Linux开发板 开发板底板原理图版本:V2.1 核心板原理图版本:V1.6 LCD :MSP2402 (IC ILI9341) 2. 查找可用引脚 开发板上引出的引脚是在JP6上,只看JP6会发现没有可用的SPI引脚&…