Java的引用——强引用 、软引用、弱引用、虚引用

本文介绍了Java中除基本数据类型外的引用类型,以及java.lang.ref包下的引用对象类。详细阐述了强、软、弱、虚四种引用类型,包括其定义、特点及对垃圾回收的影响,还通过示例说明弱引用可防止内存泄漏,最后总结软、弱引用的异同。

先知

  • Java中除了八大基本数据类型,其他都是引用类型,指向各种不同的对象。
  • java.lang.ref包下提供了引用对象类(共包括五个类:PhantomReference、Reference、ReferenceQueue、SoftReference、WeakReference),支持在某种程度上与垃圾回收器GC(垃圾回收机制回收某个对象主要是看是否有引用指向这个对象)之间的交互。
  • 对象分类:强可达对象、软可达对象、弱可达对象、虚可达对象、不可达对象
    强可达对象:如果某一线程可以不必遍历所有引用对象而直接到达一个对象,则该对象是强可达对象。新创建的对象对于创建它的线程而言是强可达对象。 
    软可达对象:如果一个对象不是强可达对象,但通过遍历某一软引用可以到达它,则该对象是软可达对象。 
    弱可达对象:如果一个对象既不是强可达对象,也不是软可达对象,但通过遍历弱引用可以到达它,则该对象是弱可达对象。当清除对某一弱可到达对象的弱引用时,便可以终止此对象了。 
    虚可达对象:如果一个对象既不是强可达对象,也不是软可达对象或弱可达对象,它已经终止,并且某个虚引用在引用它,则该对象是虚可达对象。
    不可达对象:最后,当不能以上述任何方法到达某一对象时,该对象是不可达对象,因此可以回收此对象。

Java的引用

如上所知,Java中把对象的引用分成了四个级别,分别为:强引用 、软引用、弱引用、虚引用。

而Java中提供这四种引用类型主要有两个目的:划分对象不同的可达性GC对对象回收的影响

强引用

  • 强引用:是指创建一个对象并把这个对象赋给一个引用变量。
  • 表现:Object object =new Object();
  • 特点:只要强引用存在,GC永远不会回收该对象。JVM内存空间不足时,它宁愿抛出OutOfMemory错误,也不会回收该对象。如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,就可以根据具体的垃圾回收机制被回收。

软引用

  • 软引用:SoftReference,如果一个对象具有软引用,内存空间足够时,GC就不会回收它。
  • 特点:
  1. SoftReference保存对一个Java对象的软引用,该软引用的存在不妨碍GC对该对象的回收。也就是说,在GC对这个对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用;一旦GC回收该对象之后,get()方法将返回null。
  2. 软引用对象最常用于实现内存敏感的缓存,比如图片缓存。
  3. 使用软引用能防止MemoryLeak,增强程序的健壮性。

弱引用

  • 弱引用:WeakReference,弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象(前提是只被弱引用,没有其他强引用等)。
  • 举例:为什么Android自定义内部类AsyncTask要使用WeakReference?
  • 因为内部类MyAsyncTask会隐式持有外部类Activity,当结束Activity时MyAsyncTask持有的Activity是弱引用,那么Activity能被正常GC,不会引发内存泄漏。

虚引用

  • 虚引用:PhantomReference,最弱的一种引用关系,如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被GC回收。
  • 为了确保可回收的对象仍然保持原状,虚引用的指示对象不能被获取,即虚引用的get方法总是返回 null。虚引用唯一目的是能在这个对象被GC回收时收到一个系统通知。

表格对比

引用类型GC回收时机用途
强引用不回收最常使用
软引用内存不足时回收缓存、防止内存泄漏等
弱引用每次GC时回收缓存、防止内存泄漏等
虚引用随时可能被回收

在对象被GC回收时收到一个系统通知

总结

总的来说,强引用是我们最常使用的,而对于其他三种类型的引用,使用得最多的就是软引用和弱引用。这两种既有相似之处又有区别,它们都是用来描述非必需对象的,但是被软引用关联的对象只有在内存不足时才会被回收,而被弱引用关联的对象在每次GC时会被回收。

<think>嗯,用户是在深入探讨Java的四种引用类型,看来是个有经验的开发者呢。之前已经详细解释了OOM,现在转向内存管理的核心机制。用户引用的资料很专业,特别是那个软引用内存图的描述很形象——m对象在栈,软引用对象在堆,数组对象也是堆内对象,三者通过不同引用关联。 用户可能正在设计高性能应用或缓存系统,需要精准控制对象生命周期。ta特意强调“不是OOM问题”,说明需求很聚焦。从引用材料看,引用的队列机制和弱引用的监听器应用可能是ta最想弄清的难点。 关于四种引用的区别,需要突出三个维度:回收条件、实际应用、代码表现。特别要注意: 1)强引用软引用在缓存设计的取舍:强引用导致OOM风险,软引用自动释放但可能影响性能 2)弱引用在ThreadLocal防泄漏的原理要讲透 3)引用的特殊之处在于get()永远返回null,必须配合队列使用那个代码示例很说明问题 内存泄漏预防的场景可以补充:比如Android开发中常用弱引用处理Handler,避免Activity无法回收。最后的相关问题要引导到实用层面,比如结合Spring框架的缓存实现。 </think>### Java四种引用类型的核心区别与应用场景 #### **一、核心特性对比** | **引用类型** | **回收条件** | **代码表现** | **典型应用场景** | |--------------|----------------------------------------|---------------------------------------|--------------------------------| | **强引用** | **永不回收**(除非显式置为 `null`) | `Object obj = new Object();` | 核心业务对象,如数据库连接[^1] | | **软引用** | **内存不足时回收**(OOM前触发) | `SoftReference<Object> ref = new SoftReference<>(obj);` | 图片/数据缓存系统[^2] | | **弱引用** | **下次GC必定回收**(无视内存状态) | `WeakReference<Object> ref = new WeakReference<>(obj);` | `WeakHashMap`、监听器列表[^3] | | **引用** | **对象回收时通知**(无法获取对象值) | `PhantomReference<Object> ref = new PhantomReference<>(obj, queue);` | 堆外内存清理跟踪[^4] | #### **二、关键技术细节** 1. **软引用 vs 弱引用** - 软引用:内存阈值触发回收(JVM参数 `-XX:SoftRefLRUPolicyMSPerMB` 控制) - 弱引用:**只要发生GC**立即回收(无论内存是否充足) > 示例:缓存系统推荐软引用(如 `SoftCache`),而 `ThreadLocal` 使用弱引用防内存泄漏[^2] 2. **引用的特殊机制** - 必须绑定引用队列 `ReferenceQueue` - `get()` **永远返回 `null`**,仅通过队列感知对象回收 ```java ReferenceQueue<Object> queue = new ReferenceQueue<>(); PhantomReference<Object> ref = new PhantomReference<>(new Object(), queue); System.gc(); // 对象回收后,ref 被加入 queue (可通过 queue.poll() 检测)[^4] ``` 3. **引用队列(ReferenceQueue)的作用** - 软/弱/引用均可关联队列 - **对象被回收后**,引用对象自动入队,便于执行后续清理 ```java WeakReference<Object> ref = new WeakReference<>(obj, queue); if (queue.poll() != null) { // 执行资源释放操作 } ``` #### **三、内存回收逻辑** ```mermaid graph LR A[强引用] -->|对象存活| B(GC Roots可达) C[软引用] -->|内存不足| D(触发回收) E[弱引用] -->|任何GC| F(立即回收) G[引用] -->|对象回收时| H(入队通知) ``` #### **四、典型应用场景** 1. **强引用**:Spring单例Bean、数据库连接池 2. **软引用**: - 图片缓存(`LruCache` 的备选方案) - 高频查询结果缓存(内存紧张时自动释放) 3. **弱引用**: - `WeakHashMap` 存储元数据(键自动回收) - 事件监听器列表(防止因未注销导致内存泄漏) 4. **引用**: - `DirectByteBuffer` 的堆外内存跟踪 - 资源清理钩子(如文件句柄关闭)[^4] > **关键区别**:强引用是默认对象生存的基石,软引用弱引用实现**内存敏感型缓存**,引用专注**对象终结处理**[^2][^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值