Java面试之Java中的强软弱虚四种引用

轻敏吖_2538

轻敏吖_2538

2026-01-08

504人浏览

原创

强引用不会被gc回收,哪怕内存溢出;软引用在内存不足时才回收,适合内存敏感型缓存;弱引用在每次gc时都可能被回收,用于无泄漏映射;虚引用仅用于跟踪对象回收时间点,必须配合referencequeue使用。

java面试之java中的强软弱虚四种引用

强引用不会被GC回收,哪怕内存溢出也不会

只要对象有强引用指向它,JVM 就认定这个对象“正在使用”,无论当前堆内存多么紧张,GC 都不会回收它。这是最常见、最“霸道”的引用类型。

典型写法:

Object obj = new Object();
这里的 obj 就是强引用。只要 obj 还在作用域内(没被赋值为 null,也没超出作用域),对应对象就绝对安全。

容易踩的坑:

  • 缓存场景下误用强引用,导致大量对象长期驻留堆中,引发 OutOfMemoryError: Java heap space
  • 忘记置 null 或及时释放集合引用(比如静态 Map 不断 put),造成内存泄漏

软引用只在内存不足时才回收,适合做内存敏感型缓存

SoftReference 的核心行为是:JVM 在抛出 OutOfMemoryError 之前,会尝试回收所有软引用指向的对象。它比强引用“松”一点,但比弱引用“倔”一点。

实操建议:

  • 用在图片缓存、JSON 解析结果缓存等「有用但非必需」的场景
  • 构造时可传入 ReferenceQueue 监听是否被回收:
    ReferenceQueue<object> queue = new ReferenceQueue();
    SoftReference<object> ref = new SoftReference(new Object(), queue);</object></object>
  • 获取对象必须判空:Object obj = ref.get(); if (obj != null) { ... },因为 get() 可能返回 null

注意:JDK 8+ 中软引用的回收策略受 -XX:SoftRefLRUPolicyMSPerMB 影响,默认每 MB 堆空间保留软引用 1000ms,不是“越晚用越优先保留”——这点常被误解。

弱引用只要GC发生就可能被回收,适合构建无内存泄漏的映射关系

WeakReference 的特点是:下一次 GC(哪怕是 Young GC)都可能把它干掉。它不阻止对象被回收,只提供一种“观察式”访问能力。

Miller CSV TSV JSON 数据处理器
Miller CSV TSV JSON 数据处理器

Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。

下载

典型用途:

  • WeakHashMap 的 key 是弱引用,避免 key 对象无法释放导致 value 永远不能被回收
  • 监听器解注册、临时上下文绑定(如 ThreadLocal 内部也依赖弱引用防止内存泄漏)

实操要点:

  • 永远不要假设 WeakReference.get() 一定返回非空值
  • 不要用弱引用实现“延迟初始化缓存”,它太不可控;该用软引用或 Caffeine
  • 弱引用对象被回收后,其关联的 ReferenceQueue 会收到通知,可用于清理资源

虚引用唯一作用是跟踪对象被回收的时间点,必须配合ReferenceQueue使用

PhantomReference 是最特殊的:它的 get() 方法永远返回 null,你根本拿不到它引用的对象。它存在的唯一意义,是在对象被 GC 后,往注册的 ReferenceQueue 里塞一个通知。

真实使用场景极少,但关键:

  • 替代 finalize() 实现更可控、更及时的资源清理(比如直接内存 ByteBuffer 的清理)
  • JDK 自身在 DirectByteBuffer 中用虚引用 + Cleaner(本质是虚引用增强版)管理堆外内存

必须注意:

  • 虚引用必须与 ReferenceQueue 一起使用,否则毫无意义
  • 对象进入 ReferenceQueue 时,已经处于“finalizable”之后、“已回收”之前的状态,此时对象内存尚未释放,但逻辑上已不可达
  • 别试图在 enqueue 后再通过虚引用访问对象——get() 永远是 null

虚引用的复杂性不在语法,而在于它把对象生命周期的控制权从 JVM 手动交还给程序员,稍有不慎就会漏掉清理或重复清理。真正要用它,往往意味着你在写框架级代码,而不是业务逻辑。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java js json 作用域

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2023.08.07

1935

5

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.23

2542

1

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

2023.10.13

896

3

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

2025.09.10

2839

7

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

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

2023.09.22

509

3

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

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

2024.03.01

1638

6

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

4427

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2048

6

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

2025.09.05

390

5

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习