0

0

什么是Java的垃圾回收机制(GC)_可达性分析算法与引用计数法对比

P粉602998670

P粉602998670

发布时间:2026-02-12 16:20:02

|

322人浏览过

|

来源于php中文网

原创

java弃用引用计数法因循环引用致内存泄漏、多线程更新开销大、内存浪费;gc roots包括栈中局部变量、静态变量、常量、jni引用及被锁对象;引用类型决定对象存活权重而非可达性。

什么是java的垃圾回收机制(gc)_可达性分析算法与引用计数法对比

Java为什么不用引用计数法做GC判定

因为循环引用会导致内存泄漏,JVM直接弃用——不是实现不了,而是它在Java这种强面向对象、大量使用复杂引用关系的场景下不可靠。

常见错误现象:a.next = bb.next = a,然后 a = null; b = null;,这两个对象本该回收,但引用计数始终为1,永远卡住。

  • 每次赋值、传参、出作用域都要原子更新计数器,多线程下开销大,还得加锁或CAS,拖慢吞吐
  • 每个对象头上得多塞一个整型字段(通常4字节),堆内存浪费明显,对小对象尤其不划算
  • Python能用是因为有weakref兜底+周期性扫描辅助清理;Java选择从根出发一次性厘清关系,更稳

可达性分析里的GC Roots到底指哪些对象

GC Roots不是抽象概念,而是JVM明确定义的几类“绝对不能被回收”的活跃引用源,所有存活对象都必须能从它们出发被找到。

典型场景:你写了个static List<string> cache = new ArrayList()</string>,哪怕没其他代码访问它,这个cache也因是方法区静态变量而成为GC Roots,它引用的所有字符串都活得好好的。

立即学习Java免费学习笔记(深入)”;

Knowt
Knowt

Knowt是一款AI驱动的在线学习工具

下载
  • 虚拟机栈中正在执行的方法的局部变量(比如Object obj = new Object()里的obj
  • 方法区里的静态变量(static字段)、常量(final static String这类)
  • 本地方法栈中JNI调用持有的对象引用(如通过System.loadLibrary加载的native代码里还在用的对象)
  • 正在被同步块锁定的对象(synchronized(obj)中的obj在锁未释放前也算Root)

可达性分析不是“实时扫描”,它有明确触发时机

很多人误以为对象一不可达就立刻回收——其实GC Roots遍历只发生在GC启动那一刻,中间发生的引用变化要等下次GC才生效。

容易踩的坑:在一次Full GC前疯狂创建短命对象并快速置null,但若它们恰好被某个长期存活对象临时引用过(比如进了缓存又删掉),就可能因“上次GC时还活着”而撑过本轮,撑到下一轮才被发现不可达。

  • Young GC只扫描新生代,但GC Roots全量扫描(包括老年代里的静态变量),所以耗时比想象中高
  • CMS和G1等并发收集器会用三色标记法分阶段处理,过程中需处理“对象在标记中被修改”的写屏障开销
  • 不要依赖“对象变成null后马上释放内存”,JVM只保证“下次GC时可能回收”,不承诺时间点

引用类型(强/软/弱/虚)影响的是“是否算GC Roots链上的一环”

不是所有引用都一样硬。Java用四种引用语义控制对象在GC过程中的“存活权重”,核心是让GC策略更贴近业务意图。

例如用WeakHashMap做缓存,key是弱引用,只要没有强引用指向那个key,下一次GC就会把它连同对应value一起踢掉——这比手动维护清理逻辑干净得多。

  • 强引用:最常见,如Object o = new Object(),只要它在GC Roots链上,就不会被回收
  • 软引用:内存不足时才回收,适合缓存(SoftReference
  • 弱引用:GC时不管内存足不足都回收,适合关联生命周期(WeakReference
  • 虚引用:唯一用途是收到ReferenceQueue通知,用于堆外资源清理(PhantomReference

真正复杂的是三色标记并发下的漏标问题,以及Finalizer机制带来的二次标记负担——这些细节藏在HotSpot源码里,日常开发只要记住:引用类型改变的不是“能不能被找到”,而是“找到后要不要留它一命”。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

708

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

243

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

705

2024.03.01

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1550

2023.10.24

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

56

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

58

2025.11.27

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

509

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

214

2023.09.04

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

4

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.5万人学习

C# 教程
C# 教程

共94课时 | 9.3万人学习

Java 教程
Java 教程

共578课时 | 64.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号