探索 Java 垃圾收集:对象存活判定、回收流程与内存策略

个人主页-爱因斯晨

文章专栏-JAVA学习笔记

热门文章-赛博算命

在这里插入图片描述

一、引言

在 Java 技术体系里,垃圾收集器(Garbage Collection,GC)与内存分配策略是自动内存管理的核心支撑。深入探究其原理与机制,对优化程序内存性能、规避内存泄漏与溢出等问题意义重大,是理解 Java 运行时环境的关键环节

二、GC 基础与核心问题

(一)GC 概念溯源

垃圾收集技术并非 Java 首创,早在 1960 年,Lisp 语言已应用内存动态分配与垃圾收集。GC 需解决三个核心问题:

  1. 识别待回收内存:确定哪些对象已 “死亡”,即无被使用可能。
  2. 抉择回收时机:依据内存使用状况,选择合适时机触发回收。
  3. 选定回收方式:不同垃圾收集器采用各异的回收算法与实现逻辑 。

(二)对象存活判定算法

1. 引用计数算法

原理为给对象绑定引用计数器,引用建立时计数器加 1,引用失效时减 1,计数器为 0 则判定对象可回收。但存在循环引用缺陷,如代码所示:

public class ReferenceCountingGC {public Object instance = null;private static final int _1MB = 1024 * 1024;private byte[] bigSize = new byte[2 * _1MB];public static void testGC() {ReferenceCountingGC objA = new ReferenceCountingGC();ReferenceCountingGC objB = new ReferenceCountingGC();objA.instance = objB;objB.instance = objA;objA = null;objB = null;System.gc();}
}

objAobjB相互引用,虽无实际访问路径,但引用计数不为 0,算法无法回收,故主流 Java 虚拟机弃用该算法。

2. 可达性分析算法

主流商用语言(如 Java、C#)采用的对象存活判定算法。以 “GC Roots” 为起始节点集,依据引用关系遍历搜索,无引用链连接的对象判定为可回收。Java 中,GC Roots 涵盖:

  • 虚拟机栈本地变量表引用对象,如方法内参数、局部变量。
  • 方法区静态属性与常量引用对象,像类的静态变量、字符串常量池引用。
  • 本地方法栈 JNI(Native 方法)引用对象。
  • 虚拟机内部核心引用,包括 Class 对象、常驻异常对象(如 NullPointerException )等 。
    在这里插入图片描述

三、引用分类及特性(JDK 1.2+)

JDK 1.2 拓展引用概念,按强度分为四类,各有独特内存管理行为:

(一)强引用

程序中最常见,如 Object obj = new Object() 。只要引用有效,对象不会被回收,是对象强存活的保障,支撑程序基本对象引用逻辑。

(二)软引用

用于描述非必需但仍具使用价值的对象,内存不足即将抛出溢出异常前,会触发软引用对象回收。通过 SoftReference 实现,代码示例:

SoftReference<Object> softRef = new SoftReference<>(new Object());
Object obj = softRef.get(); 

适用于缓存场景,内存紧张时释放非必需对象,平衡内存使用与功能需求。

(三)弱引用

强度弱于软引用,垃圾收集时,无论内存是否充足,弱引用关联对象都会被回收。借助 WeakReference 实现:

WeakReference<Object> weakRef = new WeakReference<>(new Object());
Object obj = weakRef.get(); 

常用于弱关联对象管理,如观察者模式中临时关联,避免因对象弱引用导致内存无法释放。

(四)虚引用

又称幽灵 / 幻影引用,不影响对象生命周期,也无法通过其获取对象,主要用于接收对象回收系统通知,由 PhantomReference 实现。是内存回收事件监听的特殊手段,可在对象回收时执行特定资源清理等操作 。

四、对象回收流程与机制

对象经可达性分析判定为不可达后,需历经两次标记才会被回收:

(一)首次标记与筛选

对象无 GC Roots 引用链时,触发首次标记。随后筛选是否需执行 finalize() 方法,未重写该方法或方法已执行过的对象,直接判定为可回收。

(二)二次标记与挽救

需执行 finalize() 的对象,被移入F - Queue队列,由 Finalizer 线程执行该方法。若对象在 finalize() 中重新建立引用链(如关联到类变量 ),二次标记时会被移出回收队列;否则,执行回收。但 finalize() 存在运行代价高、不确定性大、无法保证调用顺序等问题,推荐以 try - finally 替代,示例代码展现对象自我拯救过程:

public class FinalizeEscapeGC {public static FinalizeEscapeGC SAVE_HOOK = null;public void isAlive() {System.out.println("yes, i am still alive :)");}@Overrideprotected void finalize() throws Throwable {super.finalize();System.out.println("finalize method executed!");FinalizeEscapeGC.SAVE_HOOK = this;}public static void main(String[] args) throws Throwable {// 首次拯救逻辑SAVE_HOOK = new FinalizeEscapeGC();SAVE_HOOK = null;System.gc();Thread.sleep(500); if (SAVE_HOOK != null) {SAVE_HOOK.isAlive();} else {System.out.println("no, i am dead :(");}// 二次拯救(失败,因 finalize 仅执行一次)SAVE_HOOK = null;System.gc();Thread.sleep(500); if (SAVE_HOOK != null) {SAVE_HOOK.isAlive();} else {System.out.println("no, i am dead :(");}}
}

五、方法区的回收机制

方法区(如 HotSpot 的元空间 / 永久代 )常被误解为无垃圾收集,实则不然,其回收聚焦以下两部分:

(一)常量池回收

若常量池中的常量(如字符串 )无对象引用,且虚拟机无其他引用,可被回收。如字符串 “java” ,若系统无对应引用,内存回收时可能被清理,优化常量池内存占用。

(二)无用类回收

判定类为 “无用” 需满足三个条件:

  1. 类及派生子类无实例,Java 堆中不存在该类相关实例。
  2. 加载该类的类加载器被回收,此条件在自定义类加载器场景中较难满足,需精心设计。
  3. 该类对应的 java.lang.Class 对象无引用,无法通过反射访问类方法。

Java 虚拟机允许回收满足条件的类,但非强制。在反射、动态代理等场景,需虚拟机具备类型卸载能力,可通过 -verbose:class-XX:+TraceClassLoading-XX:+TraceClassUnLoading(部分需 FastDebug 版支持 )查看类加载 / 卸载信息,保障方法区内存健康。

六、结论

Java 垃圾收集器与内存分配策略,构建起自动内存管理的核心体系。从对象存活判定的算法演进,到引用分类的精细管控,再到对象回收流程的严谨执行与方法区回收的特殊处理,共同保障程序内存高效利用。深入理解该体系,是优化程序性能、解决内存问题的关键。后续将进一步探究具体垃圾收集器(如 Serial、G1 等 )的实现与内存分配策略细节,持续深化 Java 内存管理研究,为 Java 开发者筑牢技术根基,助力打造更高效、稳定的Java应用 。

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

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

相关文章

hbase资源和数据权限控制

hbase适合大数据量下点查 https://zhuanlan.zhihu.com/p/471133280 HBase支持对User、NameSpace和Table进行请求数和流量配额限制&#xff0c;限制频率可以按sec、min、hour、day 对于请求大小限制示例&#xff08;5K/sec,10M/min等&#xff09;&#xff0c;请求大小限制单位如…

大数据-275 Spark MLib - 基础介绍 机器学习算法 集成学习 随机森林 Bagging Boosting

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大模型篇章已经开始&#xff01; 目前已经更新到了第 22 篇&#xff1a;大语言模型 22 - MCP 自动操作 FigmaCursor 自动设计原型 Java篇开…

Delphi 实现远程连接 Access 数据库的指南

方法一&#xff1a;通过局域网共享 Access 文件&#xff08;简单但有限&#xff09; 步骤 1&#xff1a;共享 Access 数据库 将 .mdb 或 .accdb 文件放在局域网内某台电脑的共享文件夹中。 右键文件夹 → 属性 → 共享 → 启用共享并设置权限&#xff08;需允许网络用户读写&a…

VR视频制作有哪些流程?

VR视频制作流程知识 VR视频制作&#xff0c;作为融合了创意与技术的复杂制作过程&#xff0c;涵盖从初步策划到最终呈现的多个环节。在这个过程中&#xff0c;我们可以结合众趣科技的产品&#xff0c;解析每一环节的实现与优化&#xff0c;揭示背后的奥秘。 VR视频制作有哪些…

文件上传/下载接口开发

接口特性 文件传输接口与传统接口的核心差异体现在数据传输格式&#xff1a; 上传接口采用 multipart/form-data 格式支持二进制文件传输下载接口接收二进制流并实现本地文件存储 文件上传接口开发 接口规范 请求地址&#xff1a;/createbyfile 请求方式&#xff1a;POST…

深入学习RabbitMQ队列的知识

目录 1、AMQP协议 1.1、介绍 1.2、AMQP的特点 1.3、工作流程 1.4、消息模型 1.5、消息结构 1.6、AMQP 的交换器类型 2、RabbitMQ结构介绍 2.1、核心组件 2.2、最大特点 2.3、工作原理 3、消息可靠性保障 3.1、生产端可靠性 1、生产者确认机制 2、持久化消息 3.…

【计算机网络】NAT、代理服务器、内网穿透、内网打洞、局域网中交换机

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;计算机网络 &#x1f339;往期回顾&#x1f339;&#xff1a;【计算机网络】数据链路层——ARP协议 &#x1f516;流水不争&#xff0c;争的是滔滔不息 一、网络地址转…

[论文阅读] 人工智能 | 大语言模型计划生成的新范式:基于过程挖掘的技能学习

#论文阅读# 大语言模型计划生成的新范式&#xff1a;基于过程挖掘的技能学习 论文信息 Skill Learning Using Process Mining for Large Language Model Plan Generation Andrei Cosmin Redis, Mohammadreza Fani Sani, Bahram Zarrin, Andrea Burattin Cite as: arXiv:2410.…

C文件操作2

五、文件的随机读写 这些函数都需要包含头文件 #include<stdio.h> 5.1 fseek 根据文件指针的位置和偏移量来定位文件指针&#xff08;文件内容的光标&#xff09; &#xff08;重新定位流位置指示器&#xff09; int fseek ( FILE * stream, long int offset, int or…

react私有样式处理

react私有样式处理 Nav.jsx Menu.jsx vue中通过scoped来实现样式私有化。加上scoped&#xff0c;就属于当前组件的私有样式。 给视图中的元素都加了一个属性data-v-xxx&#xff0c;然后给这些样式都加上属性选择器。&#xff08;deep就是不加属性也不加属性选择器&#xff09; …

【信创-k8s】海光/兆芯+银河麒麟V10离线部署k8s1.31.8+kubesphere4.1.3

❝ KubeSphere V4已经开源半年多&#xff0c;而且v4.1.3也已经出来了&#xff0c;修复了众多bug。介于V4优秀的LuBan架构&#xff0c;核心组件非常少&#xff0c;资源占用也显著降低&#xff0c;同时带来众多功能和便利性。我们决定与时俱进&#xff0c;使用1.30版本的Kubernet…

单片机内部结构基础知识 FLASH相关解读

一、总线简单说明 地址总线、控制总线、数据总线 什么是8位8051框架结构的微控制器&#xff1f; 数据总线宽度为8位&#xff0c;即CPU一次处理或传输的数据量为8位&#xff08;1字节&#xff09; 同时还有一个16位的地址总线&#xff0c;这个地方也刚好对应了为什么能看到内存…

HTTPS加密的介绍

HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff0c;超文本传输安全协议&#xff09;是HTTP协议的安全版本。它在HTTP的基础上加入了SSL/TLS协议&#xff0c;用于对数据进行加密&#xff0c;并确保数据传输过程中的机密性、完整性和身份验证。 在HTTPS出现之前&a…

【freertos-kernel】stream_buffer

文章目录 补充任务通知发送处理ulTaskGenericNotifyTakexTaskGenericNotifyWait 清除xTaskGenericNotifyStateClearulTaskGenericNotifyValueClear 结构体StreamBufferHandle_tStreamBufferCallbackFunction_t 创建xStreamBufferGenericCreatestream buffer的类型 删除vStreamB…

在word中点击zotero Add/Edit Citation没有反应的解决办法

重新安装了word插件 1.关掉word 2.进入Zotero左上角编辑-引用 3.往下滑找到Microsoft Word&#xff0c;点重新安装加载项

新华三H3CNE网络工程师认证—Easy IP

Easy IP 就是“用路由器自己的公网IP&#xff0c;给全家所有设备当共享门牌号”的技术&#xff01;&#xff08;省掉额外公网IP&#xff0c;省钱又省配置&#xff01;&#xff09; 生活场景对比&#xff0c;想象你住在一个小区&#xff1a;普通动态NAT&#xff1a;物业申请了 …

算法打开13天

41.前 K 个高频元素 &#xff08;力扣347题&#xff09; 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输入: nums [1,1,1,2,2,3], k 2 输出: [1,2]示例 2: 输入: nums [1], k 1 输出: …

LabVIEW与PLC液压泵测控系统

针对液压泵性能测试场景&#xff0c;采用LabVIEW与西门子 PLC 控制系统&#xff0c;构建高精度、高可靠性的智能测控系统。通过选用西门子 PLC、NI 数据采集卡、施耐德变频电机等&#xff0c;结合LabVIEW 强大的数据处理与界面开发能力&#xff0c;实现液压泵压力、流量、转速等…

应急响应靶机-web2-知攻善防实验室

题目&#xff1a; 前景需要&#xff1a;小李在某单位驻场值守&#xff0c;深夜12点&#xff0c;甲方已经回家了&#xff0c;小李刚偷偷摸鱼后&#xff0c;发现安全设备有告警&#xff0c;于是立刻停掉了机器开始排查。 这是他的服务器系统&#xff0c;请你找出以下内容&#…

Python制作史莱姆桌面宠物!可爱的

史莱姆桌面宠物 一个可爱的桌面史莱姆宠物&#xff0c;它会在您的任务栏上移动并提供可视化设置界面。 这里写目录标题 史莱姆桌面宠物功能特点安装与运行直接运行方式创建可执行文件 使用说明自定义GIF说明打包说明开源地址 功能特点 可爱的史莱姆在任务栏上自动移动支持…