JVM——垃圾收集策略

news2025/7/19 6:47:19

GC的基本问题

什么是GC?

GC 是 garbage collection 的缩写,意思是垃圾回收——把内存(特别是堆内存)中不再使用的空间释放掉;清理不再使用的对象。

为什么要GC?

堆内存是各个线程共享的空间,不能无节制的使用。服务器运行的时间通常都很长。累积的对象也会非常多。这些对象如果不做任何清理,任由它们数量不断累加,内存很快就会耗尽。所以GC就是要把不使用的对象都清理掉,把内存空间空出来,让项目可以持续运行下去。

如何判断对象已死?(GC触发的条件

引用计数算法

简单来说,引用计数算法就是在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。

但这时会出现一个问题,即当两个对象相互进行引用时,也就意味着,它永远都无法”死亡“,就无法进行回收。

Java虚拟机并不是通过引用计数算法来判断对象是否存活的。

可达性分析算法

通过一系列被称为 “GC Roots” 的对象作为起始点,从这些节点向下搜索,搜索走过的路径叫引用链。当一个对象到 GC Roots 没有任何引用链相连时,证明此对象不可用,可被判定为 “死亡” 。

在 Java 语言中,可作为 GC Roots 的对象包括:

  1. 在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使用到的 参数、局部变量、临时变量等。

  2. 在方法区中类静态属性引用的对象,譬如Java类的引用类型静态变量。

  3. 在方法区中常量引用的对象,譬如字符串常量池(String Table)里的引用。

  4. 在本地方法栈中JNI(即通常所说的Native方法)引用的对象。

  5. Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如 NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器。

  6. 所有被同步锁(synchronized关键字)持有的对象。

  7. 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。

再谈引用

引用大至分为四种:

  • 强引用:new出来的对象 内存溢出也不会进行回收
  • 软引用:只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存, 才会抛出内存溢出异常。
  • 弱引用:只要有垃圾收集就会回收
  • 虚引用:回收时收到系统通知

生存还是死亡?(是否真正进行回收)

即使在可达性分析算法中判定为不可达的对象,也不是“非死不可”的,这时候它们暂时还处于“缓 刑”阶段,要真正宣告一个对象死亡,至少要经历两次标记过程:

  • 第一次标记:是否有与GC Roots相连接的引用链
  • 第二次筛选:此对象是否有必要执行finalize()方法(判断对象能否通过finalize()方法实现自我拯救(避免被回收 )

 finalize()是java.lang.Object类的方法,所有对象默认继承这个方法。方法体内是空的,说明如果子类不重写这个方法,那么不执行任何逻辑。

回收方法区(永久代)

永久代的垃圾收集主要回收两部分内容:废弃常量和无用的类。

废弃常量回收比较简单,就是看是否仍有其他地方引用了此字面量,若无引用,则被回收。而判断一个类是否需要被回收条件比较苛刻,需要同时满足下面三个条件才能算是“无用的类”:

  1. 该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例
  2. 加载该类的ClassLoader已经被回收
  3. 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法

分代收集理论

弱分代假说(新生代)

绝大多数对象都是朝生夕灭的。

强分代假说(老年代)

熬过越多次垃圾收集过程的对象就越难以消亡。

垃圾收集器的设计原则

将Java堆根据年龄(年龄即对象熬过垃圾收集过程的次数)划分出不同的区域进行存储。当一个对象存活时间越长,年龄越大,我们就将其移动到老年代区域,这样将新生代和老年代分开管理。每次回收时只关注如何保留少量存活而不是去标记那些大量将要被回收的对 象,就能以较低代价回收到大量的空间;

 跨代引用假说

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

当新生代和老年代互相引用,是应该倾向于同时生存或者同时消亡的。如果某个新生代对象存在跨代引用,由于老年代对象难以 消亡,该引用会使得新生代对象在收集时同样得以存活,进而在年龄增长之后晋升到老年代中,这时 跨代引用也随即被消除了。

如何记录每一个对象是否存在及存在哪些跨代引用?

在新生代上建立一个全局的数据结构(记忆集),这个结构把老年代划分成若干小块,标识出老年代的哪一块内存会存在跨代引用。跨代引用的小块内存里的对象才会被加入到GC Roots进行扫描。

垃圾收集算法

标记-清除算法(老年代

首先标记出需要回收的对象,在标记完成后统一回收掉所有的被标记对象。

缺点

  1. 执行效率不稳定:标记和清除两个过 程的执行效率都随对象数量增长而降低;
  2. 内存空间的碎片化问题:标记、清除之后会产生大 量不连续的内存碎片,空间碎片太多可能会导致当以后在程序运行过程中需要分配较大对象时无法找 到足够的连续内存而不得不提前触发另一次垃圾收集动作。 

标记-复制算法(新生代)

它将可用内存按需要分成两块(实际情况不一定2块,块的大小比例不一定),每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

新生代通常使用复制算法,因为新生代中对象大多 “朝生夕灭”,每次垃圾收集时有大量对象死去,只有少量存活,复制算法能高效地将少量存活对象复制到另一块空间,实现快速回收。

优点:每次只对其中一块进行GC,不用考虑内存碎片的问题,并且实现简单,运行高效。(适用于新生代,效率高)

缺点:内存缩小了一半。复制的目标空间需要依赖其他空间进行分配担保(将超出的部分直接放入到老年代区域中)。效率随对象存活率升高而降低:当对象存活率较高时,需要进行较多复制操作,效率将会变低。

Appel式回收

把新生代分为一块较大的Eden空间和两块较小的 Survivor空间(8:1:1),每次分配内存只使用Eden和其中一块Survivor。

发生垃圾搜集时,将Eden和Survivor中仍 然存活的对象一次性复制到另外一块Survivor空间上,然后直接清理掉Eden和已用过的那块Survivor空间。

当Survivor空间不足以容纳一次Minor GC之后存活的对象时,就需要依赖其他内存区域(将超出的部分直接放入到老年代区域中)。

标记-整理算法(老年代)

使用“标记-整理”算法:先标记,再把所有存活的对象向一端移动,然后直接清理端边界意外的内存。

老年代中对象存活率高,没有额外空间对其进行分配担保。如果在老年代使用复制算法,由于存活对象多,复制操作会比较频繁,效率低下且成本较高。

优点:不会像复制算法、效率随对象存活率升高而变低。不会像标记-清除算法,产生内存碎片(因为清除前,进行了整理,存活对象都集中到空间一侧)。

缺点:主要是效率问题:除像标记-清除算法的标记过程外,还多了需要整理的过程,效率更低。 

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

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

相关文章

马克·雷伯特:用算法让机器人飞奔的人

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 马克雷伯特:用算法让机器人飞奔的人 一、天才的起点 在机器人领域,有一个名字如雷贯耳——马克雷伯特(Marc Raibert)。作为波士顿动力公司(Boston…

信创系统资产清单采集脚本:主机名+IP+MAC 一键生成 CSV

原文链接:信创系统资产清单采集脚本:主机名IPMAC 一键生成 CSV Hello,大家好啊!今天给大家带来一篇在信创终端操作系统上自动批量采集主机名、IP 和 MAC 并导出为 CSV 表格的实战文章!本方案使用 sshpass 和 Bash 脚本…

SpringBoot获取用户信息常见问题(密码屏蔽、驼峰命名和下划线命名的自动转换)

文章目录 一、不返回password字段二、返回的createTime和updateTime为空原因解决:开启驼峰命名和下划线命名的自动转换 设置返回的日期格式 一、不返回password字段 在字段上面添加JsonIgnore注解即可 JsonIgnore // 在把对象序列化成json字符串时,忽略…

Mac下安装Python3,并配置环境变量设置为默认

下载Python 访问Python官方网站 https://www.python.org/ 首先获得python3安装路径 执行命令: which python3 以我这台电脑为例,路径为:/Library/Frameworks/Python.framework/Versions/3.9/bin/python3 编辑 bash_profile 文件 然后用 vim 打…

Linux-04-用户管理命令

一、useradd添加新用户: 基本语法: useradd 用户名:添加新用户 useradd -g 组名 用户:添加新用户到某个组二、passwd设置用户密码: 基本语法: passwd 用户名:设置用户名密码 三、id查看用户是否存在: 基本语法: id 用户名 四、su切换用户: 基本语法: su 用户名称:切换用…

【进阶】--函数栈帧的创建和销毁详解

目录 一.函数栈帧的概念 二.理解函数栈帧能让我们解决什么问题 三.相关寄存器和汇编指令知识点补充 四.函数栈帧的创建和销毁 4.1.调用堆栈 4.2.函数栈帧的创建 4.3 函数栈帧的销毁 一.函数栈帧的概念 --在C语言中,函数栈帧是指在函数调用过程中,…

【一】 基本概念与应用领域【数字图像处理】

考纲 文章目录 1 概念2005甄题【名词解释】2008、2012甄题【名词解释】可考题【简答题】可考题【简答题】 2 应用领域【了解】2.1 伽马射线成像【核医学影像】☆2.2 X射线成像2.3 紫外波段成像2.4 可见光和红外波段成像2.5 微波波段成像2.6 无线电波段成像2.7 电子显微镜成像2…

NU1680低成本、无固件、高集成度无线充电电源接收器

无线充电 电子产品具有无线充电功能使用会更便利,介绍一款低成本、无固件、高集成度无线充电电源接收器NU1680 原理图和BOM可点绑定资源下载,LC部分电容建议X7R。 Load空载切满载测试 (CC Mode) – 尽量保证电子负载没有过冲 – 电子负载不要从0到满…

2025MathorCup数学应用挑战赛B题

目录 模型建立与求解 1.问题一的模型建立与求解 1.1 搬迁补偿模型设计 1.2 住户是否搬迁的应对策略与分析 1.3 定量讨论 2.问题二的模型建立与求解 2.1 搬迁方案模型的优化介绍 2.2 模型的评估 2.3 模型结果 3.问题三的模型建立与求解 3.1 拐点存在性分析模型的建立 3.2 模型的…

组件的基本知识

组件 组件的基本知识 组件概念组成步骤好处全局注册生命周期scoped原理 父子通信步骤子传父 概念 就是将要复用的标签,抽离放在一个独立的vue文件中,以供主vue文件使用 组成 三部分构成 template:HTML 结构 script: JS 逻辑 style: CSS 样…

Origin绘图操作:图中迷你图绘制

一、背景描述 Origin绘图时,局部数据变化较小,在整体图片中表现为局部曲线重叠在一起,图中y1和y2在x0-2时重叠在一起,需要将局部放大,绘制迷你图 二、实现方法 1.在左边工具栏选择放大镜,按住ctrl在图中…

数据升降级:医疗数据的“时空穿梭“系统工程(分析与架构篇)

一、核心挑战与量化分析 1. 版本演化困境的深度解析 (1) 格式断层的结构化危机 数据转换黑洞:某医疗信息平台(2021-2023)统计显示: 数据类型CDA R1→R2转换失败率R2→FHIR转换失败率关键失败点诊断记录28.4%19.7%ICD编码版本冲突(18.7%)用药记录15.2%12.3%剂量单位标准化…

【GESP】C++三级练习 luogu-B2089 数组逆序重存放

GESP三级练习,一维数组练习(C三级大纲中5号知识点,一维数组),难度★☆☆☆☆。 题目题解详见:https://www.coderli.com/gesp-3-luogu-b2089/ 【GESP】C三级练习 luogu-B2089 数组逆序重存放 | OneCoderGE…

Copilot 上线深度推理智能体 Researcher

近日,微软推出两款首创的工作场景推理智能体:Researcher(研究员)和Analyst(分析师)。它们能以安全合规的方式访问您的工作数据(包括邮件、会议、文件、聊天记录等)及互联网信息&…

日常开发小Tips:后端返回带颜色的字段给前端

一般来说,展示给用户的字体格式,都是由前端控制,展现给用户; 但是当要表示某些字段的数据为异常数据,或者将一些关键信息以不同颜色的形式呈现给用户时,而前端又不好判断,那么就可以由后端来控…

如何在WordPress网站中设置双重验证,提升安全性

随着互联网的不断进步,网站的安全问题越来越受到重视。尤其对于WordPress这样常用的建站平台,安全性显得尤为重要。尽管WordPress自带一定的安全性,但仅依靠用户名和密码的登录方式仍然存在风险。因此,启用“双重验证”便成为了提…

Python 虚拟环境管理:venv 与 conda 的选择与配置

文章目录 前言一、虚拟环境的核心价值1.1 依赖冲突的典型场景1.2 隔离机制实现原理 二、venv 与 conda 的架构对比2.1 工具定位差异2.2 性能基准测试(以创建环境 安装 numpy 为例) 三、venv 的配置与最佳实践3.1 基础工作流3.2 多版本 Python 管理 四、…

8.Android(通过Manifest配置文件传递数据(meta-data))

配置文件 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"><applicationandroid:allowBackup"tr…

三网通电玩城平台系统结构与源码工程详解(二):Node.js 服务端核心逻辑实现

本篇文章将聚焦服务端游戏逻辑实现&#xff0c;以 Node.js Socket.io 作为主要通信与逻辑处理框架&#xff0c;展开用户登录验证、房间分配、子游戏调度与事件广播机制的剖析&#xff0c;并附上多个核心代码段。 一、服务端文件结构概览 /server/├── index.js …

02_java的运行机制以及JDKJREJVM基本介绍

1、运行机制 2、JDK&JRE&JVM JDK 基本介绍 &#xff08;1&#xff09; JDK 的全称(Java Development Kit Java开发工具包) JDK JRE java的开发工具 [ java, javac, javadoc, javap等 ] &#xff08;2&#xff09;JDK是提供给Java开发人员使用的&#xff0c;其…