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

深入理解Java中的四类引用:强、软、弱、虚引用

在Java开发中,我们通常使用new关键字创建对象,这些默认都是​​强引用​​。但Java实际上提供了四种不同强度的引用类型,它们与JVM的内存管理密切相关。理解这些引用类型,能帮助我们编写更高效、更健壮的Java程序,尤其是在处理内存敏感型应用时。

一、引用类型概览

Java从1.2版本开始引入了java.lang.ref包,提供了四种引用类型,按引用强度从强到弱排列如下:

引用类型

回收时机

典型用途

强引用

默认

永不回收(除非不可达)

常规对象引用

软引用

SoftReference

内存不足时回收

内存敏感缓存

弱引用

WeakReference

下次GC时回收

临时缓存、WeakHashMap

虚引用

PhantomReference

随时可能回收

对象回收跟踪

二、强引用(Strong Reference)

​定义​​:我们日常使用的普通对象引用就是强引用。

Object obj = new Object(); // 强引用

​特点​​:

  • 只要强引用存在,垃圾收集器就​​永远不会回收​​被引用的对象

  • 即使内存不足,JVM抛出OOM也不会回收强引用对象

  • 显式置为null或超出作用域后,对象变为可回收状态

​内存泄漏场景​​:

List<Object> list = new ArrayList<>();
while(true) {list.add(new Object()); // 强引用导致OOM
}

三、软引用(Soft Reference)

​定义​​:描述一些​​有用但非必需​​的对象。

SoftReference<byte[]> softRef = new SoftReference<>(new byte[10 * 1024 * 1024]);

​特点​​:

  • 在内存充足时,软引用对象不会被回收

  • 当内存不足时(即将OOM前),这些对象会被回收

  • 适合实现​​内存敏感缓存​

​缓存示例​​:

public class ImageCache {private final Map<String, SoftReference<Bitmap>> cache = new HashMap<>();public void put(String key, Bitmap bitmap) {cache.put(key, new SoftReference<>(bitmap));}public Bitmap get(String key) {SoftReference<Bitmap> ref = cache.get(key);return ref != null ? ref.get() : null;}
}

四、弱引用(Weak Reference)

​定义​​:描述​​非必需​​对象,比软引用更弱。

WeakReference<Object> weakRef = new WeakReference<>(new Object());

​特点​​:

  • 无论内存是否充足,​​下次GC时​​弱引用对象都会被回收

  • 常用于实现​​临时缓存​​(如WeakHashMap)

  • 不会阻止对象被finalize

​WeakHashMap示例​​:

WeakHashMap<Key, Value> map = new WeakHashMap<>();
Key key = new Key();
map.put(key, new Value());key = null; // 下次GC时,Entry会被自动清除

五、虚引用(Phantom Reference)

​定义​​:最弱的引用,无法通过虚引用获取对象。

ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);

​特点​​:

  • 任何时候都可能被回收

  • 必须与ReferenceQueue配合使用

  • 主要用于​​对象回收跟踪​​(如NIO的DirectBuffer清理)

​资源清理示例​​:

public class ResourceHolder {private final ReferenceQueue<Object> queue = new ReferenceQueue<>();private final List<PhantomReference<Object>> refs = new ArrayList<>();public void register(Object resource, Runnable cleanup) {PhantomReference<Object> ref = new PhantomReference<>(resource, queue) {@Overridepublic void clear() {cleanup.run();super.clear();}};refs.add(ref);// 通常会有线程监控queue并处理}
}

六、引用队列(ReferenceQueue)

软/弱/虚引用都可以关联引用队列,当引用对象被回收时,引用本身会入队:

ReferenceQueue<Object> queue = new ReferenceQueue<>();
WeakReference<Object> ref = new WeakReference<>(new Object(), queue);// 监控队列的线程
new Thread(() -> {while(true) {try {Reference<?> ref = queue.remove();// 执行清理操作} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}).start();

七、实战应用场景

  1. ​缓存实现​​:

    • 一级缓存(强引用) + 二级缓存(软引用)

    • 使用WeakHashMap实现临时缓存

  2. ​内存泄漏防护​​:

    // 防止监听器导致的内存泄漏
    public void addListener(Object listener) {listeners.add(new WeakReference<>(listener));
    }
  3. ​资源清理​​:

    // 确保native资源释放
    try (DirectBuffer buf = allocateDirect()) {// 使用虚引用跟踪buf
    }

八、注意事项

  1. 软引用在客户端和服务端的表现可能不同(某些JVM实现可能更激进)

  2. 弱引用不适合做缓存(回收太频繁)

  3. 虚引用必须配合引用队列使用

  4. 引用对象本身(如SoftReference实例)仍是强引用,需注意管理

总结

Java的四类引用构成了灵活的内存管理机制:

  • ​强引用​​:常规对象生命周期控制

  • ​软引用​​:"柔性"缓存,内存不足时释放

  • ​弱引用​​:不影响GC的临时关联

  • ​虚引用​​:对象回收的精确通知

合理使用这些引用类型,可以帮助我们:

  • 优化内存使用

  • 防止内存泄漏

  • 实现高效缓存

  • 精确控制资源释放

理解这些引用类型,是成为Java高级开发者的重要一步。在你的项目中,是否遇到过适合使用这些引用类型的场景呢?

http://www.dtcms.com/a/338562.html

相关文章:

  • 【科研绘图系列】R语言绘制多组火山图
  • 第六天~提取Arxml中CAN Node节点信息Creat_ECU
  • STL库——string(类模拟实现)
  • ETLCloud中的数据转化规则是什么意思?怎么执行
  • QT示例 基于Subdiv2D的Voronoi图实现鼠标点击屏幕碎裂掉落特效
  • Linux中Docker k8s介绍以及应用
  • C++ 默认参数深度解析【C++每日一学】
  • Flutter AlwaysScrollableScrollPhysics详解
  • LIA-X - 一张照片生成任意表情肖像动画视频 精准操控面部动作 支持50系显卡 一键整合包下载
  • RWA加密金融高峰论坛星链品牌全球发布 —— 稳定币与Web3的香港新篇章
  • C# winform FTP功能
  • openldap安装 -添加条目
  • 项目管理.管理理念学习
  • 跟踪不稳定目标:基于外观引导的运动建模实现无人机视频中的鲁棒多目标跟踪
  • 第10章 React应用测试
  • 一、快速掌握python中的序列、集合和字典的用法(数据容器)
  • RxJava 在 Android 即时通讯中的应用:封装、处理与控制
  • 《WASM驱动本地PDF与Excel预览组件的深度实践》
  • 达梦数据库表恢复方法总结
  • 章11:管理网络
  • 网络基础——网络传输基本流程
  • Android Coil 3拦截器Interceptor计算单次请求耗时,Kotlin
  • GPT-4.1旗舰模型:复杂任务的最佳选择及API集成实践
  • 基于prompt的生物信息学:多组学分析的新界面
  • RecSys:粗排模型和精排特征体系
  • 力扣57:插入区间
  • Apache IoTDB:大数据时代时序数据库选型的技术突围与实践指南
  • 【力扣 Hot100】 刷题日记——双指针的经典应用
  • 论文阅读:Prompt Optimization in Large Language Models
  • @Linux问题 :bash fork Cannot allocate memory 错误分析与解决方案