深入探究 JVM 堆的垃圾回收机制(二)— 回收

GC Roots 枚举需要遍历整个应用程序的上下文,而在进行可达性分析或者垃圾回收时,如果我们还是进行全堆扫描及收集,那么会非常耗时。JVM 将堆分为新生代及老生代,它们的回收频率及算法不一样。

1 回收算法

在进行可达性分析时,我们会对对象进行标记:存活及待回收。然后再进行回收。

标记-清除

统一回收所有被标记为“待回收”的对象。

缺陷:1)执行效率不稳定,如果大部分对象需要回收,那清除工作将增加。2)内存空间碎片化,会产生大量不连续的内存碎片。

标记-复制

半区复制,将空间平分为2,每次只用其中1块,每次回收时将存活的对象复制到另一块,将当前块一次性清理掉。

缺陷:1)如果大部分对象是存活的,就会产生很大的内存复制开销。2)可用内存缩小到原来一半,内存利用率不高。

标记-整理

让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存。

缺陷:如果存活对象分布比较分散,那么移动对象将很耗时。

表 回收算法

“标记-清除”因为“碎片问题”在虚拟机中较少使用,“碎片问题”会带来垃圾回收频繁、大型数据无法存储等问题。

1.1 分代收集

弱分代假说:绝大多数对象都是朝生夕灭。

强分代假说:熬过越多次垃圾收集的对象就越难以消亡。

JVM 按照对象年龄(熬过垃圾收集过程的次数,默认15次)将堆划分为新生代与老生代。

新生代

依据弱分代假说,每次回收只关注如何保留少部分存活的对象。

算法:标记-复制

老生代

依据强分代假说,以较低频率回收这个区域。

算法:标记-整理

表 新生代与老生代

1.1.1 新生代 Appel 式垃圾回收

将新生代划分为三块空间:Eden、Servivor1、Servivor2,内存大小比例为8:1:1。

每次只使用Eden和一块Servivor,垃圾回收时,将它们当作还存活的对象一次性复制到另一块Servivor中,然后清理掉使用的Eden及Servivor块。

PS:回收时,如果Eden及Servivor存活下来的对象超过Servivor容量时,会将溢出的对象复制到老生代。

1.1.2 晋升到老生代

晋升到老生代有如下场景:

  1. 对象年龄达到阈值。
  2. 大对象(大小超过设定的阈值)直接分配至老生代。避免大对象在新生代频繁复制。
  3. 老生代空间担保失败,Minor GC完成后存活的对象大小超过一块Servivor的值。
  4. 动态年龄判定,如果年龄小等于X的对象总大小超过Servivor容量的50%,则所有年龄>=X的对象直接晋升。

1.1.3 Minor GC 与 Full GC

纬度

Minor GC

Full GC

作用区域

新生代

整个堆(新生代+老生代)+方法区

触发

频率高。

当Eden区空间不足时触发。

(并非每次Eden满都触发,若开启空间分配担保,则可能直接触发Full GC)。

频率低。

  1. 老生代空间不足。
  2. 方法区空间不足。
  3. 显式调用:System.gc()
  4. 空间分配担保失败。

算法

标记-复制

标记-整理/标记-清除

表 Minor GC 与Full GC的对比

1.2 跨代引用

新生代的对象可能被老生代引用。Minor GC时,进行可达性分析前还需要将引用了新生代对象的老生代对象加入到GC Roots中。

跨代引用假说:跨代引用相对于同代引用来说仅占少数。

1.2.1 卡表

为了能快速收集到引用了新生代的老生代对象,在新生代上建立一个全局的“记忆集”,来记录老生代中跨代引用的信息。

“卡表”是记忆集的一种实现,是一个字节类型的数组。数组中每个元素对应老生代中一块固定大小的内存区域。该区域称为卡页(默认512字节)。当卡页中有对象存在跨代引用时,卡表对应数组的元素值为1,否则为0。

1.2.2 卡表的“伪共享”

“伪共享”是一种性能问题。

操作系统中内存与缓存的取值最小单位是缓存行(64字节),多线程并发的场景下,不同线程对不同卡表项修改可能操作的是同一缓存行,从而引发频繁的缓存同步,降低性能。

优化方案:

  1. 在标记卡表前,如果该条目未被标记,才能进行标记。(减少不必要的写操作)
  2. 卡表稀疏化,调整卡表条目粒度。

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

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

相关文章

CSS 学习笔记 - 蓝桥杯重点整理

1. CSS 基础语法 核心知识点 选择器 声明块结构三种引入方式&#xff1a;行内/内部/外部常用选择器类型&#xff1a;标签/类/ID/通配符 <!-- 行内样式 --> <p style"color: red;">红色文字</p><!-- 内部样式 --> <style>/* 标签选…

UML的使用

process on 在线使用 UML概念 UML &#xff1a;统一建模语言(Unified Modeling Language&#xff0c;是用来设计软件的可视化建模语言。 1. 类图 1.1 概念 类图&#xff08;Class Diagram&#xff09;是UML中用于描述系统静态结构的图形化工具。它展示了系统的类、接口、它…

【C++】入门

1.命名空间 1.1 namespace的价值 在C/C中&#xff0c;变量&#xff0c;函数和后面要学到的类都是大量存在的&#xff0c;这些变量&#xff0c;函数和类的名称将存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c;…

数据库练习2

目录 1.向heros表中新增一列信息&#xff0c;添加一些约束&#xff0c;并尝试查询一些信息 2.课堂代码练习 插入语句 INSERT INTO 删除语句DELETE和TRUNCATE 更新语句UPDATE和replace 查询语句SELECT 条件查询 查询排序 聚合函数 分组查询 3.题目如下 一、单表查询 …

w266农产品直卖平台的设计与实现

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

2025新版懒人精灵零基础安装调试+lua基础+UI设计交互+常用方法封装+项目实战+项目打包安装板块-视频教程(初学者必修课)

2025新版懒人精灵零基础安装调试lua基础UI设计交互常用方法封装项目实战项目打包安装板块-视频教程(初学者必修课)&#xff1a; 1.懒人精灵核心API基础和lua基础视频教程&#xff1a;https://www.bilibili.com/video/BV1Vm9kYJEfM/ 温馨提示&#xff1a;所有视频请用电脑浏览…

CCF-CSP认证 202206-2寻宝!大冒险!

题目描述 思路 有一张绿化图和藏宝图&#xff0c;其中绿化图很大&#xff08;二维数组在限定的空间内无法存储&#xff09;&#xff0c;而藏宝图是绿化图中的一部分&#xff0c;对于绿化图和藏宝图&#xff0c;左下角的坐标为(0, 0)&#xff0c;右上角的坐标是(L, L)、(S, S)&…

Qt下集成大华网络相机SDK示例开发

文章目录 前言一、下载并集成大华网络相机SDK二、示例实现功能三、示例完整代码四、下载链接总结 前言 近期在Qt环境下进行大华网络相机的使用&#xff0c;发现官网下载的SDK中提供的示例没有Qt的demo&#xff0c;通过学习其提供的MFC示例代码&#xff0c;我在这里也实现了一个…

[学习笔记] 部署Docker搭建靶场

前言 我们需要部署Docker来搭建靶场题目&#xff0c;他可以提供一个隔离的环境&#xff0c;方便在不同的机器上部署&#xff0c;接下来&#xff0c;我会记录我的操作过程&#xff0c;简单的部署一道题目 Docker安装 不推荐在物理机上部署&#xff0c;可能会遇到一些问题&…

网络华为HCIA+HCIP IPv6

目录 IPv4现状 IPv6基本报头 IPv6扩展报头 IPv6地址 IPv6地址缩写规范 ​编辑 IPv6地址分配 IPv6单播地址分配 IPv6单播地址接口标识 IPv6常见单播地址 - GUA &#xff08;2 / 3 开头&#xff09; IPv6常见单播地址 - ULA IPv6常见单播地址 - LLA IPv6组播地…

可视化动态表单动态表单界的天花板--Formily(阿里开源)

文章目录 1、Formily表单介绍2、安装依赖2.1、安装内核库2.2、 安装 UI 桥接库2.3、Formily 支持多种 UI 组件生态&#xff1a; 3、表单设计器3.1、核心理念3.2、安装3.3、示例源码 4、场景案例-登录注册4.1、Markup Schema 案例4.2、JSON Schema 案例4.3、纯 JSX 案例 1、Form…

C++::多态

目录 一.多态的概念 二.多态的定义及实现 二.1多态的构成条件 二.2虚函数 1.虚函数的写法 2.虚函数的重写/覆盖 3.协变 二.3析构函数的重写 二.4override和final关键字 ​编辑二.5重载/重写/隐藏的对比 三.多态的运行原理&#xff08;一部分&#xff09; 四.多态的常…

Mistral AI发布开源多模态模型Mistral Small 3.1:240亿参数实现超越GPT-4o Mini的性能

法国人工智能初创公司Mistral AI于2025年3月正式推出新一代开源模型Mistral Small 3.1 &#xff0c;该模型凭借240亿参数的轻量级设计&#xff0c;在多项基准测试中表现优异&#xff0c;甚至超越了Google的Gemma 3和OpenAI的GPT-4o Mini等主流专有模型。 1、核心特性与优势 多…

从零开发数据可视化

一、可视化模版展示 二、知识及素材准备 div css 布局flex布局Less原生js jquery 的使用rem适配echarts基础 相关js、images、font百度网盘下载链接&#xff1a; 通过百度网盘分享的文件&#xff1a;素材1 链接: https://pan.baidu.com/s/1vmZHbhykcvfLzzQT5USr8w?pwdwjx9…

WSL git文件异常 所有文件均显示已修改

如图&#xff0c;文件中没有任何修改&#xff0c;但是都显示多了一个^M 原因&#xff1a;是因为在Windows系统中git clone的文件夹&#xff0c;在WSL中会显示冲突。 解决方案&#xff1a;删掉之前在windows下git clone的文件夹&#xff0c; 然后在WSL中重新git clone

基于STM32进行FFT滤波并计算插值DA输出

文章目录 一、前言背景二、项目构思1. 确定FFT点数、采样率、采样点数2. 双缓存设计 三、代码实现1. STM32CubeMX配置和HAL库初始化2. 核心代码 四、效果展示和后话五、项目联想与扩展1. 倍频2. 降频3. 插值3.1 线性插值3.2 样条插值 一、前言背景 STM32 对 AD 采样信号进行快…

ENSP学习day9

ACL访问控制列表实验 ACL&#xff08;Access Control List&#xff0c;访问控制列表&#xff09;是一种用于控制用户或系统对资源&#xff08;如文件、文件夹、网络等&#xff09;访问权限的机制。通过ACL&#xff0c;系统管理员可以定义哪些用户或系统可以访问特定资源&#x…

Ubuntu22.04通过DKMS包安装Intel WiFi系列适配器(网卡驱动)

下载驱动包 访问 backport-iwlwifi-dkmshttps://launchpad.net/ubuntu/source/backport-iwlwifi-dkms 网站&#xff0c;找到适用于Ubuntu 22.04的update版本&#xff08;如backport-iwlwifi-dkms_xxxx_all.deb&#xff09;&#xff0c;下载至本地。 安装驱动 在下载目录中执行以…

c#难点整理2

1.对象池的使用 就是先定义一系列的对象&#xff0c;用一个&#xff0c;调一个。 public class ObjectPool<T> where T : new(){private Queue<T> pool; // 用于存储对象的队列private int maxSize; // 对象池的最大容量// 构造函数public ObjectPool(int maxSi…

音频录制小妙招-自制工具-借助浏览器录一段单声道16000采样率wav格式音频

先看效果 1、打开页面 2、点击开始录音&#xff0c;弹出权限提示&#xff0c;点击“仅这次访问时允许” 3、录完后&#xff0c;点击停止 4、文件自动下载到默认目录 上代码 js 部分 document.addEventListener(DOMContentLoaded, () > {const startBtn document.getEleme…