JVM垃圾回收

1. Java垃圾回收机制

  • 为了让程序员更专注于代码的实现,而不用过多的考虑内存释放的问题,所以,在Java语言中,有了自动的垃圾回收机制,也就是我们熟悉的GC(Garbage Collection)。
  • 有了垃圾回收机制后,程序员只需要关心内存的申请即可,内存的释放由系统自动识别完成。
  • 当对象被认定为垃圾,就会用垃圾回收器采用对应的垃圾回收算法,自动垃圾回收

2. 怎么判定对象是垃圾

  • 如果一个对象没有任何的引用指向它了,那么这个对象现在就是垃圾,如果定位了垃圾,则有可能会被垃圾回收器回收。
  • 如何判定什么是垃圾?
    • 引用计数法
    • 可达性分析算法

2.1 引用计数法

概念

一个对象被引用了一次,在当前的对象头上递增一次引用次数,如果这个对象的引用次数为0,代表这个对象可回收

String demo = new String(“123”);
在这里插入图片描述

String demo = null;
在这里插入图片描述

优点

  • 实时性较高,无需等到内存不够的时候,才开始回收,运行时根据对象的计数器是否为0,就可以直接回收。
  • 在垃圾回收过程中,应用无需挂起。如果申请内存时,内存不足,则立刻报OOM错误。
  • 区域性,更新对象的计数器时,只是影响到该对象,不会扫描全部对象。

缺点

  • 每次对象被引用时,都需要去更新计数器,有一点时间开销。
  • 浪费CPU资源,即使内存够用,仍然在运行时进行计数器的统计。
  • 无法解决循环引用问题,会引发内存泄露。(最大的缺点)

循环引用

当对象间出现了循环引用的话,则引用计数法就会失效
在这里插入图片描述
先执行右侧代码的前4行代码
在这里插入图片描述
目前上方的引用关系和计数都是没问题的,但是,如果代码继续往下执行,如下图
在这里插入图片描述
虽然a和b都为null,但是由于a和b存在循环引用,这样a和b永远都不会被回收。

2.2 可达性分析算法

概念

  • 会存在一个根节点【GC Roots】,引出它下面指向的下一个节点,再以下一个节点开始找出它下面的节点,依次往下类推。直到所有的节点全部遍历完毕。

根对象是那些肯定不能当做垃圾回收的对象,就可以当做根对象
局部变量,静态方法,静态变量,类信息
核心是:判断某对象是否与根对象有直接或间接的引用,如果没有被引用,则可以当做垃圾回收

在这里插入图片描述

GC ROOTS

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
/**
demo是栈帧中的本地变量,当 demo = null 时,由于此时 demo 充当了 GC Root 的作用,
demo与原来指向的实例 new Demo() 断开了连接,对象被回收。
*/
public class Demo {public static  void main(String[] args) {Demo demo = new Demo();demo = null;}
}
  • 方法区中类静态属性引用的对象
/**
当栈帧中的本地变量 b = null 时,由于 b 原来指向的对象与 GC Root (变量 b) 断开了连接,
所以 b 原来指向的对象会被回收,而由于我们给 a 赋值了变量的引用,
a在此时是类静态属性引用,充当了 GC Root 的作用,它指向的对象依然存活!
*/
public class Demo {public static Demo a;public static  void main(String[] args) {Demo b = new Demo();b.a = new Demo();b = null;}
}
  • 方法区中常量引用的对象
/**
常量 a 指向的对象并不会因为 demo 指向的对象被回收而回收
*/
public class Demo {public static final Demo a = new Demo();public static  void main(String[] args) {Demo demo = new Demo();demo = null;}
}

优点

  • 有效处理循环引用
  • 准确性高
  • 无需频繁更新引用计数

缺点

  • 遍历对象时需要暂停用户线程(STW),导致程序短暂卡顿。堆内存越大,停顿时间可能越长,对实时性要求高的应用(如交易系统)影响较大。
  • 实现复杂度高 需要维护正确的GC Roots集合,并处理多线程环境下的对象状态变化(如并发标记时的“浮动垃圾”)。并发收集器(如CMS、G1)需额外处理漏标、误标等问题,算法实现较为复杂。
  • 若GC Roots定义不当(如遗漏某些根对象),可能导致内存泄漏或误回收。例如,未及时清理的静态变量可能长期占据内存。

3. 垃圾回收算法

3.1 标记清除算法

概念

  • 标记清除算法,是将垃圾回收分为2个阶段,分别是标记和清除
    • 根据可达性分析算法得出的垃圾进行标记
    • 对这些标记为可回收的内容进行垃圾回收

[图片]

  • 标记清除算法解决了引用计数算法中的循环引用的问题,没有从root节点引用的对象都会被回收。

缺点:

  • 效率较低,标记和清除两个动作都需要遍历所有的对象,并且在GC时,需要停止应用程序,对于交互性要求比较高的应用而言这个体验是非常差的。
  • (重要)通过标记清除算法清理出来的内存,碎片化较为严重,因为被回收的对象可能存在于内存的各个角落,所以清理出来的内存是不连贯的。

3.2 标记复制算法

  • 复制算法的核心就是,将原有的内存空间一分为二,每次只用其中的一块,在垃圾回收时,将正在使用的对象复制到另一个内存空间中,然后将该内存空间清空,交换两个内存的角色,完成垃圾的回收。
  • 如果内存中的垃圾对象较多,需要复制的对象就较少,这种情况下适合使用该方式并且效率比较高,反之,则不适合。

在这里插入图片描述

  1. 将内存区域分成两部分,每次操作其中一个。
  2. 当进行垃圾回收时,将正在使用的内存区域中的存活对象移动到未使用的内存区域。当移动完对这部分内存区域一次性清除。
  3. 周而复始。

优点:

  • 在垃圾对象多的情况下,效率较高
  • 清理后,内存无碎片

缺点:

  • 分配的2块内存空间,在同一个时刻,只能使用一半,内存使用率较低

3.3 标记整理算法

  • 标记整理算法是在标记清除算法的基础之上,做了优化改进的算法。
  • 和标记清除算法一样,也是从根节点开始,对对象的引用进行标记
  • 在清理阶段,并不是简单的直接清理可回收对象,而是将存活对象都向内存另一端移动,然后清理边界以外的垃圾,从而解决了碎片化的问题。

在这里插入图片描述

  1. 标记垃圾。
  2. 需要清除向右边走,不需要清除的向左边走。
  3. 清除边界以外的垃圾。

优缺点

标记清除算法,解决了标记清除算法的碎片化的问题
同时,标记整理算法多了一步,对象移动内存位置的步骤,其效率也有一定的影响。
复制算法对比:复制算法标记完就复制,但标记整理算法得等把所有存活对象都标记完毕,再进行整理

3.4 分代收集算法

概述

在java8时,堆被分为了两份:新生代和老年代【1:2】,在java7时,还存在一个永久代。
在这里插入图片描述

对于新生代,内部又被分为了三个区域。Eden区,S0区,S1区【8:1:1】
当对新生代产生GC:MinorGC【young GC】
当对老年代代产生GC:Major GC
当对新生代和老年代产生FullGC: 新生代 + 老年代完整垃圾回收,暂停时间长,应尽力避免!

工作机制

  • 新创建的对象,都会先分配到eden区
  • 当伊甸园内存不足,标记(可达性分析)伊甸园与 from(现阶段没有)的存活对象
  • 将存活对象采用复制算法复制到 to 中,复制完毕后,伊甸园和 from 内存都得到释放
  • 经过一段时间后伊甸园的内存又出现不足,标记eden区域to区存活的对象,将存活的对象复制到from区
  • 当幸存区对象熬过几次回收(最多15次),晋升到老年代(幸存区内存不足或大对象会导致提前晋升)

4. 垃圾收集器

4.1 CMS(并发)垃圾收集器

概念

CMS全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,该回收器是针对老年代垃圾回收的,是一款以获取最短回收停顿时间为目标的收集器,停顿时间短,用户体验就好。其最大特点是在进行垃圾回收时,应用仍然能正常运行。

CMS工作阶段

  1. 初始标记(Initial Mark):STW,标记GC Roots直接关联的对象。
  2. 并发标记(Concurrent Mark):与用户线程并发,遍历老年代。
  3. 重新标记(Remark):STW,修正并发标记期间的变更(使用增量更新或SATB)。
  4. 并发清除(Concurrent Sweep):删除不可达对象,不整理内存。

在这里插入图片描述

优点

  1. 低停顿时间(Low Pause)
    • 并发标记与清除:大部分标记(Mark)和清除(Sweep)阶段与用户线程并发执行,显著减少 Stop-The-World(STW) 停顿时间,适合对延迟敏感的应用。
  2. 分代回收优化
    • 主要针对 老年代(Old Generation) 设计,与新生代的 ParNew 收集器配合使用,形成分代回收体系,减少全局停顿频率。
  3. 标记-清除算法
    • 采用 标记-清除(Mark-Sweep) 而非压缩(Compact),减少STW时间,但会导致内存碎片(需权衡)。

缺点

  1. 内存碎片问题
    • 标记-清除算法不整理内存,长期运行后老年代可能出现碎片,导致 Full GC 时被迫触发单线程的 Serial Old 收集器(压缩整理),造成长时间STW。
  2. CPU资源敏感
    • 并发阶段占用CPU资源(与用户线程竞争),可能导致应用吞吐量下降,尤其在多核资源不足时。
  3. 浮动垃圾(Floating Garbage)
    • 并发标记期间用户线程可能产生新垃圾(标记后新死亡的对象),需预留足够内存空间,否则可能触发 并发失败(Concurrent Mode Failure),退化为Full GC。

4. 无法处理巨型对象

  • 对占用连续内存的 大对象(Humongous Object) 支持不足,分配失败时易触发GC。

4.2 G1垃圾回收器

概述

  • 应用于新生代和老年代,在JDK9之后默认使用 G1
  • 划分成多个区域,每个区域都可以充当 eden,survivor,old, humongous,其中 humongous 专为大对象准备
  • 采用复制算法
  • 响应时间与吞吐量兼顾
  • 分成三个阶段:新生代回收、并发标记、混合收集
  • 如果并发失败(即回收速度赶不上创建新对象速度),会触发 Full GC
    在这里插入图片描述

流程

Young Collection(年轻代垃圾回收)
  • 初始时,所有区域都处于空闲状态
    [图片]

  • 创建了一些对象,挑出一些空闲区域作为伊甸园区存储这些对象
    在这里插入图片描述

  • 当伊甸园需要垃圾回收时,挑出一个空闲区域作为幸存区,用复制算法复制存活对象,需要暂停用户线程
    在这里插入图片描述
    在这里插入图片描述

  • 随着时间流逝,伊甸园的内存又有不足

  • 将伊甸园以及之前幸存区中的存活对象,采用复制算法,复制到新的幸存区,其中较老对象晋升至老年代
    在这里插入图片描述
    在这里插入图片描述
    [图片]

Young Collection + Concurrent Mark (年轻代垃圾回收+并发标记)

当老年代占用内存超过阈值(默认是45%)后,触发并发标记,这时无需暂停用户线程
在这里插入图片描述

  • 并发标记之后,会有重新标记阶段解决漏标问题,此时需要暂停用户线程
  • 这些都完成后就知道了有哪些存活对象,随后进入混合收集阶段
  • 此时不会对所有老年代区域进行回收
  • 而是根据暂停时间目标优先回收价值高(存活对象少)的区域( Gabage First 的由来)。
    在这里插入图片描述
Mixed Collection (混合垃圾回收)

混合收集阶段中,参与复制的有 eden、survivor、old,下图显示了伊甸园和幸存区的存活对象复制
在这里插入图片描述

下图显示了老年代和幸存区晋升的存活对象的复制
在这里插入图片描述

复制完成,内存得到释放。进入下一轮的新生代回收、并发标记、混合收集

在这里插入图片描述

其中H叫做巨型对象,如果对象非常大,会开辟一块连续的空间存储巨型对象
在这里插入图片描述

优点

  1. 并行与并发结合
    • 并行:利用多线程加速垃圾回收(如Young GC、Mixed GC)。
    • 并发:标记阶段(Concurrent Marking)与用户线程并发执行,减少停顿时间(STW)。
  2. 可预测的停顿时间
    • 通过将堆划分为多个 Region,优先回收垃圾比例最高的 Region(Garbage-First 策略),允许用户设置期望的最大停顿时间(-XX:MaxGCPauseMillis),适合对延迟敏感的应用。
  3. 内存分区模型
    • 堆被划分为大小相等的 Region,支持动态分代(无需固定 Young/Old 区大小),灵活应对对象生命周期差异,减少内存碎片。
  4. 高效处理大对象
    • 专门设计 Humongous Region 存储巨型对象(如大数组),避免大对象分配时对连续内存的依赖。
  5. 高吞吐量与低延迟平衡
    • 适合大堆内存(如 4GB 以上),在吞吐量和延迟之间取得较好平衡,替代了传统的 CMS

缺点

  1. 内存占用较高
    • 维护 Region 元数据(如存活对象标记、跨 Region 引用)需要额外内存,相比 CMS 等收集器内存开销更大。
  2. Young GC 延迟较高
    • Young GC 需要 STW 暂停,若 Eden Region 较多或对象存活率高,可能导致 Young GC 时间较长。
  3. Mixed GC 依赖全局标记
    • Mixed GC(回收部分 Old Region)依赖全局并发标记结果,若并发标记失败(如堆内存不足),可能退化为 Full GC(单线程的 Serial Old),导致长时间停顿。
  4. 配置调优复杂
    • 需要根据应用负载调整参数(如 Region 大小、MaxGCPauseMillis、IHOP 阈值等),默认配置未必最优,调优门槛较高。
  5. 不适用于极小堆
    • 对于堆内存较小的应用(如 < 4GB),G1 的分区管理开销可能抵消其优势,此时更适合使用 Parallel GC 或 CMS。

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

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

相关文章

jmeter--(吞吐量控制器)逻辑控制器

在 JMeter 中&#xff0c;吞吐量控制器&#xff08;Throughput Controller&#xff09; 是一种逻辑控制器&#xff0c;用于控制其子节点&#xff08;请求、逻辑控制器等&#xff09;的执行次数或百分比&#xff0c;从而调整测试计划的吞吐量。它通常用于模拟不同比例的用户行为…

SpringBoot3实战(SpringBoot3+Vue3基本增删改查、前后端通信交互、配置后端跨域请求、数据批量删除(超详细))(3)

目录 一、从0快速搭建SpringBoot3工程、SpringBoot3集成MyBatis、PageHelper分页查询的详细教程。(博客链接) 二、实现前端与后端通信对接数据。(axios工具) &#xff08;1&#xff09;安装axios。(vue工程目录) &#xff08;2&#xff09;封装请求工具类。(request.js) <1&…

Atom of Thoughts for Markov LLM Test-Time Scaling论文解读

近年来&#xff0c;大型语言模型在训练规模的扩展上取得了显著的性能提升。然而&#xff0c;随着模型规模和数据量的增长遇到瓶颈&#xff0c;测试时扩展&#xff08;test-time scaling&#xff09;成为进一步提升模型能力的新方向。传统的推理方法&#xff0c;如思维链&#x…

前端字段名和后端不一致?解锁 JSON 映射的“隐藏规则” !!!

&#x1f680; 前端字段名和后端不一致&#xff1f;解锁 JSON 映射的“隐藏规则” &#x1f31f; 嘿&#xff0c;技术冒险家们&#xff01;&#x1f44b; 今天我们要聊一个开发中常见的“坑”&#xff1a;前端传来的 JSON 参数字段名和后端对象字段名不一致&#xff0c;会发生…

AI训练如何获取海量数据,论平台的重要性

引言&#xff1a;数据——AI时代的“新石油” 在人工智能和大模型技术飞速发展的今天&#xff0c;数据已成为驱动技术进步的 “ 燃料 ”。无论是训练聊天机器人、优化推荐算法&#xff0c;还是开发自动驾驶系统&#xff0c;都需要海量、多样化的数据支持。 然而&#xff0c;获…

k8s的存储

一 configmap 1.1 configmap的功能 configMap用于保存配置数据&#xff0c;以键值对形式存储。 configMap 资源提供了向 Pod 注入配置数据的方法。 镜像和配置文件解耦&#xff0c;以便实现镜像的可移植性和可复用性。 etcd限制了文件大小不能超过1M 1.2 configmap的使用…

递归、搜索与回溯第三讲:综合练习

递归、搜索与回溯第三讲&#xff1a;综合练习 1.找出所有子集的异或总和再求和2.全排列3.电话号码的字母组合4.组合5.目标和6.组合总和7.字母大小写全排列8.优美的排列9.N皇后10.有效的数独11.括号生成12.解数独13.单词搜索14.黄金矿工15.不同路径III 有决策树的递归总结&#…

Excel 小黑第12套

对应大猫13 涉及金额修改 -数字组 -修改会计专用 VLOOKUP函数使用&#xff08;查找目标&#xff0c;查找范围&#xff08;F4 绝对引用&#xff09;&#xff0c;返回值的所在列数&#xff0c;精确查找或模糊查找&#xff09;双击填充柄就会显示所有值 这个逗号要中文的不能英…

AI重构工程设计、施工、总承包行业:从智能优化到数字孪生的产业革命

摘要 AI正深度重构工程设计、施工与总承包行业&#xff0c;推动从传统经验驱动向数据智能驱动的转型。本文系统性解析AI当前在智能优化设计、施工过程管理、全生命周期数字孪生等场景的应用&#xff0c;展望未来AI在自动化决策、跨域协同等领域的潜力&#xff0c;并从投入产出…

Java高频面试之集合-15

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;解决哈希冲突有哪些方法&#xff1f; 1. 开放寻址法&#xff08;Open Addressing&#xff09; 核心思想&#xff1a;当哈…

vulhub Matrix-Breakout

1.下载靶机&#xff0c;打开靶机和kali虚拟机 2.查询kali和靶机ip 3.浏览器访问 访问81端口有登陆界面 4.扫描敏感目录 kali dirb 扫描 一一访问 robot.txt提示我们继续找找&#xff0c;可能是因为我们的字典太小了&#xff0c;我们换个扫描器换个字典试下,利用kali自带的最大…

docker-compose install nginx(解决fastgpt跨区域)

CORS前言 CORS(Cross-Origin Resource Sharing,跨源资源共享)是一种安全措施,它允许或拒绝来自不同源(协议、域名、端口任一不同即为不同源)的网页访问另一源中的资源。它的主要作用如下: 同源策略限制:Web 浏览器的同源策略限制了从一个源加载的文档或脚本如何与另一…

【Java】——方法的使用(从入门到进阶)

&#x1f381;个人主页&#xff1a;User_芊芊君子 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 &#x1f50d;系列专栏&#xff1a;【Java】内容概括 文章目录&#xff1a; 1.方法的概念及使用1.1 什么是方法&#xff1f;1.2 方法的意义1.3 方法的定义…

STM32HAL库,解决串口UART中断接收到的第一个字节数据丢失

1.问题描述&#xff1a; 只有上电后第一次接收到的第一字节数据会丢失&#xff0c;往后再接收也不会存在问题了。 2.先贴出来重写UART中断回调函数 我在接收到第一字节数据后开启定时器中断的&#xff0c;做一个超时处理&#xff0c;每次接收到数据会对定时器计数值清零&…

Linux中安装redis

Redis的安装包&#xff0c;从官方下载下来的是c语言的源码包&#xff0c;我们需要自己编译安装。具体操作步骤如下&#xff1a; 安装redis 上传redis资源包 安装C语言的编译环境 gcc yum install -y gcc-c 解压redis源码在当前目录 tar -zxvf redis-6.2.4.tar.gz 进入解压目录…

基于 SSE 和 WebSocket 的在线文本实时传输工具

简介 在线文本实时传输工具支持 SSE&#xff08;Server-Sent Events&#xff09; 和 WebSocket&#xff0c;可在不同设备间快速共享和同步文本&#xff0c;适用于跨设备协作、远程办公和即时通讯。 核心功能 实时同步&#xff1a;文本输入后&#xff0c;另一端用户可立即看到…

【UE5 PuerTS笔记】PuerTS安装

目录 1.下载PuerTS2.下载V83.创建C项目4.拷贝puerts/unreal下的Puerts目录到您项目的Plugins目录下5.解压V8到YouProject/Plugins/Puerts/ThirdParty6.在JsEnv.build.cs中修改UseV8Version设置为你所下载的版本。7.修改CSharpParamDefaultValueMetas.cs文件增加宏定义8.取消引擎…

Baklib企业CMS元数据与协作管理优化

智能元数据驱动协作流程升级 在现代企业内容管理中&#xff0c;智能元数据系统已成为提升协作效率的核心引擎。通过自动化标签分类与语义分析技术&#xff0c;Baklib实现了文档属性的动态结构化映射&#xff0c;使跨部门协作中的信息检索效率提升超40%。其可视化流程编辑器支持…

从零开始实现 C++ TinyWebServer Buffer类详解

文章目录 为什么需要Buffer缓冲区&#xff1f;Buffer 设计Buffer 成员变量实现 ReadFD() 函数实现 WriteFD() 函数实现 MakeSpace() 函数Buffer 代码Buffer 测试 在网络编程中&#xff0c;Buffer&#xff08;缓冲区&#xff09;是一个非常重要的概念&#xff0c;它可以帮助我们…

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…