当前位置: 首页 > news >正文

【JVM】根可达算法

根可达性算法可以理解为一句话:

从一批“绝对不能被回收的对象”出发,顺着引用关系往外找,能找到的对象就是存活对象,找不到的就是垃圾对象。


一、什么是 GC Root?

GC Root 就是垃圾回收时的“起点对象”。

JVM 在判断对象是否存活时,不是看这个对象有没有被别人引用,而是看:

这个对象能不能从 GC Root 出发,通过引用链找到。

比如:

A->B->C

如果A是 GC Root,那么 JVM 从A出发,可以找到B,再找到C

所以:

A、B、C 都是存活对象

但是如果有:

D->EE->D

虽然DE互相引用,但如果从任何 GC Root 都找不到它们,那么它们就是垃圾。

这也解决了引用计数法无法解决的循环引用问题


二、根可达性算法的判断过程

可以分成三步:

1. 找出 GC Root

JVM 先找到一批根对象,比如:

线程栈里的局部变量 静态变量 常量引用 JNI 本地方法引用 被 synchronized 加锁的对象

这些对象被认为是程序当前执行过程中“还可能用到的对象”。


2. 从 GC Root 出发沿引用链查找

例如:

publicclassDemo{staticObjectstaticObj=newObject();publicstaticvoidmain(String[]args){ObjectlocalObj=newObject();ObjectinnerObj=newObject();localObj=innerObj;}}

这里可能形成这样的引用关系:

GC Root | |-- staticObj | |-- main线程栈中的 localObj

只要对象能从这些 GC Root 找到,就不会被回收。


3. 找不到的对象就是垃圾

例如:

Objecta=newObject();Objectb=newObject();a=null;b=null;

ab都不再引用原来的对象后,如果这些对象也没有被其他 GC Root 间接引用,那么它们就变成垃圾对象。


三、哪些对象可以作为 GC Root?

你写的四类可以这么理解。


1. 系统类的实例对象

这个说法可以理解为:

由系统类加载器加载的一些核心类对象,或者方法区中类静态属性引用的对象,可以作为 GC Root。

更常见的面试说法是:

方法区中类静态属性引用的对象。

比如:

publicclassUserService{publicstaticObjectobj=newObject();}

这里的obj是静态变量,属于类级别的变量。

只要UserService这个类还被加载着,那么:

UserService.class -> static obj -> new Object()

这个new Object()就可以从 GC Root 找到,所以不会被回收。

可以简单记成:

静态变量引用的对象,可以作为 GC Root 直接或间接可达的对象

2. 本地方法调用相关的实例对象

也就是:

本地方法栈中 JNI 引用的对象。

Java 有时会调用 Native 方法,也就是用 C/C++ 写的方法,比如:

publicnativevoidmethod();

如果 Native 方法中持有了某个 Java 对象的引用,那么 JVM 不能随便回收这个对象。

因为 Native 代码可能还在使用它。

所以这类对象也可以作为 GC Root。

可以简单理解为:

被 native 方法引用的 Java 对象,不能被回收

3. 当前活动线程相关的实例对象

这是最常见、最重要的一类。

准确说是:

虚拟机栈中栈帧里的局部变量表引用的对象,可以作为 GC Root。

例如:

publicvoidtest(){Objectobj=newObject();}

test()方法正在执行时,obj是局部变量,存放在当前线程的栈帧中。

此时:

当前线程栈帧中的 obj -> new Object()

所以这个对象不能被回收。

再比如:

publicvoidtest(){Useruser=newUser();user.setName("Tom");}

只要test()方法还没执行结束,user引用的对象通常就是可达的。

可以简单记成:

正在运行的方法中的局部变量引用的对象,不能回收

4. 被加锁的实例对象

也就是:

被 synchronized 持有的对象,可以作为 GC Root。

例如:

Objectlock=newObject();synchronized(lock){// 临界区代码}

当线程进入synchronized(lock)代码块后,lock对象正在作为锁使用。

这个对象不能被回收,否则锁的语义就出问题了。

所以 JVM 会认为被锁持有的对象是可达的。

可以简单理解为:

正在被 synchronized 当锁用的对象,不能被回收

四、举个完整例子

publicclassDemo{staticObjectstaticObj=newObject();publicstaticvoidmain(String[]args){ObjectlocalObj=newObject();ObjectuselessObj=newObject();uselessObj=null;}}

main方法执行期间:

GC Roots | |-- staticObj -> Object1 | |-- main线程栈中的 localObj -> Object2

所以:

Object1 不会被回收 Object2 不会被回收

而:

ObjectuselessObj=newObject();uselessObj=null;

原来被uselessObj引用的对象已经找不到了。

所以:

Object3 可能被回收

注意是可能被回收,不是立刻回收。

因为 GC 什么时候发生,由 JVM 决定。


五、面试回答版本

你可以这样说:

Java 判断对象是否为垃圾,主要使用根可达性算法。JVM 会从一组 GC Roots 对象出发,沿着对象之间的引用链向下搜索。如果某个对象能够从 GC Roots 到达,说明它仍然被使用,不能回收;如果某个对象无法从任何 GC Roots 到达,那么它就可以被判定为垃圾对象。常见的 GC Roots 包括:虚拟机栈中局部变量引用的对象、方法区中静态变量或常量引用的对象、本地方法栈中 JNI 引用的对象,以及被 synchronized 锁持有的对象等。

更口语一点:

简单来说,就是从线程栈、静态变量、常量、Native 方法引用、锁对象这些根对象开始找,能找到的对象就是活的,找不到的对象就是垃圾。


你这四类可以稍微改得更标准一些:

1. 虚拟机栈中局部变量表引用的对象 2. 方法区中类静态属性引用的对象 3. 方法区中常量引用的对象 4. 本地方法栈中 JNI 引用的对象 5. 被 synchronized 持有的对象

其中你写的:

当前活动线程相关的实例对象

对应的是虚拟机栈中的局部变量引用对象

你写的:

系统类的实例对象

更标准地说应该是方法区中静态变量或常量引用的对象

http://www.jsqmd.com/news/963978/

相关文章:

  • 新手入门:零基础借助快马理解并构建你的第一个Token中转服务
  • 电源滤波电容选型:从ESR、涟波电流到实战应用
  • 实战应用:基于快马平台快速开发具备平滑过渡动画的网页日夜主题切换器
  • 澳洲集运公司推荐:适配方案汇总 - 资讯速览
  • 别再用ChatGPT写周报了!真正提升人效300%的AI工作整合范式:基于ISO/IEC 23894标准的5阶演进模型
  • 鸣潮自动化:如何让游戏帮你打工,每天节省3小时重复操作?
  • MP4视频文件损坏修复技术:Untrunc项目深度解析与实战指南
  • 效率提升秘籍:用claude code在快马平台自动生成通用工具函数库
  • AI辅助开发实践:让快马平台生成类似7cccc图片的智能图像处理代码
  • STC单片机ISP机制深度解析:从反汇编到自定义Bootloader实践
  • 2026丹阳配镜:解读行业三大核心发展趋势 - 资讯速览
  • 工程师如何构建抗压系统:从技术调试到职业韧性
  • FastGithub:5分钟搭建专属GitHub加速通道,告别访问卡顿
  • SpringSecurity源码初探
  • 实战vue3项目,用快马ai生成团队统一的vscode开发环境配置包
  • 卡片超量=流量归零?CSDN AI营销系统底层规则拆解,第4张起触发降权机制!
  • AI辅助开发:让快马智能优化你的tokenpocket钱包交互与状态管理代码
  • Notepad2-mod:轻量级文本编辑器的终极解决方案
  • 框架的核心角色
  • 大语言模型辅助智能合约静态审计:利用 AST 语法树解析与 LLM 提示词链漏洞扫描实战
  • 新手入门:基于快马平台生成第一个potplayer字幕翻译脚本
  • 2026年工衣/防静电工衣/电子厂工衣/食品厂工衣/夏天工衣供应厂家分析:透气舒适与安全防护双优之选 - 品牌企业推荐师(官方)
  • YOLO26红外小目标检测实战:缝合DASI模块,实现暗光环境下的特征极速增强
  • QGC地面站视频流拉不通?别急,先用这5个排查步骤搞定(从Ping到VLC播放器)
  • 3大核心功能彻底改变你的B站桌面体验
  • 普宁月子中心口碑排名|从月嫂、月子餐、修复三维怎么评 - 品牌观察
  • 跨学科研究新思路:怎么用 GPT-5.5 寻找不同领域之间的学术交叉点?(附实战教程)
  • Android应用保活技术突破:基于Linux特性的永生方案实现
  • 实战应用:基于js深入浅出vue理念,在快马平台快速构建博客后台管理系统
  • 嵌入式开发模块化编程实战:从Keil软仿真到工程架构设计