SoftReference & WeakReference

本文详细介绍了Java中弱引用(WeakReference)与软引用(SoftReference)的概念及应用场景。弱引用适用于需要观察对象是否已被垃圾回收的情况,而软引用则用于实现对象缓存,能在内存紧张时自动释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

如果你想写一个 Java 程序,观察某对象什么时候会被垃圾收集的执行绪清除,你必须要用一个 reference 记住此对象,以便随时观察,但是却因此造成此对象的 reference 数目一直无法为零, 使得对象无法被清除。

 java.lang.ref.WeakReference

  不过,现在有了 Weak Reference 之后,这就可以迎刃而解了。如果你希望能随时取得某对象的信息,但又不想影响此对象的垃圾收集,那么你应该用 Weak Reference 来记住此对象,而不是用一般的 reference

  A obj = new A();

    WeakReference wr = new WeakReference(obj);
  
  ...

  if (wr.get()==null) {
  
  
  System.out.println("obj 已经被清除了 ");
  
  
  } else {
  
  System.out.println("obj 尚未被清除,其信息是 "+obj.toString());
  
  }
  
  ...
  在此例中,透过 get() 可以取得此 Reference 的所指到的对象,如果传出值为 null 的话,代表此对象已经被清除。

  这类的技巧,在设计 Optimizer Debugger 这类的程序时常会用到,因为这类程序需要取得某对象的信息,但是不可以 影响此对象的垃圾收集。

  java.lang.ref.SoftReference

  Soft Reference 虽然和 Weak Reference 很类似,但是用途却不同。 被 Soft Reference 指到的对象,即使没有任何 Direct Reference,也不会被清除。一直要到 JVM 内存不足时且 没有 Direct Reference 时才会清除,SoftReference 是用来设计 object-cache 之用的。如此一来 SoftReference 不但可以把对象 cache 起来,也不会造成内存不足的错误 (OutOfMemoryError)。我觉得 Soft Reference 也适合拿来实作 pooling 的技巧。

 

    A obj = new A();

    SoftRefenrence sr = new SoftReference(obj);

 

    引用时

    if(sr!=null){

        obj = sr.get();

    }else{

        obj = new A();

        sr = new SoftReference(obj);

    }

  

<think>我们正在讨论Java中的WeakReferenceSoftReference的区别及使用场景。首先,我们需要明确这两个类都属于Java的引用类型,它们位于java.lang.ref包中,用于帮助管理内存,避免内存溢出。主要区别在于垃圾回收器(GC)对待它们的方式:1.WeakReference(弱引用):当垃圾回收器进行回收时,无论内存是否充足,都会回收被弱引用指向的对象。也就是说,只要对象只被弱引用指向,那么在下一次垃圾回收时,这个对象就会被回收。2.SoftReference(软引用):当垃圾回收器进行回收时,只有在内存不足的情况下,才会回收被软引用指向的对象。因此,软引用可以用来实现内存敏感的缓存,当内存足够时,缓存对象可以保留;当内存不足时,这些对象可以被回收,从而避免内存溢出。使用场景:-WeakReference的典型使用场景是在实现规范化映射(比如WeakHashMap)时,它不会阻止键值被垃圾回收。另外,在需要不影响垃圾回收的情况下监听对象(例如某些监听器)时也很有用。-SoftReference常用于缓存,尤其是当缓存的对象比较大,而且我们希望在不影响应用性能的前提下,在内存不足时自动清理缓存。下面我们通过代码示例来进一步说明:```javaimportjava.lang.ref.WeakReference;importjava.lang.ref.SoftReference;publicclassReferenceExample{publicstaticvoidmain(String[]args){//创建一个对象StringstrongRef=newString("Hello,World!");//创建一个弱引用,指向该对象WeakReference<String>weakRef=newWeakReference<>(strongRef);//创建一个软引用,指向该对象SoftReference<String>softRef=newSoftReference<>(strongRef);//取消强引用strongRef=null;//强制触发垃圾回收(注意:这只是建议,不能保证立即执行)System.gc();//检查弱引用:很可能已经被回收System.out.println("WeakReference:"+weakRef.get());//检查软引用:由于内存充足,可能还未被回收System.out.println("SoftReference:"+softRef.get());}}```注意:在实际运行中,垃圾回收的行为可能会因为JVM的实现和当前内存状况而有所不同。上面的代码中,我们取消了强引用后,弱引用指向的对象在垃圾回收时被回收的概率很大,而软引用指向的对象在内存充足时可能不会被回收。另外,Java还提供了PhantomReference(虚引用)和ReferenceQueue(引用队列),它们可以用于更复杂的场景,比如在对象被回收时收到通知执行清理操作。总结:-WeakReference:垃圾回收时立即回收(只要没有强引用),用于避免阻止垃圾回收的场景。-SoftReference:在内存不足时回收,用于实现缓存。相关问题:1.什么是Java的强引用?2.如何结合ReferenceQueue使用WeakReferenceSoftReference?3.在Android开发中,SoftReferenceWeakReference的使用有什么不同?4.使用WeakHashMap有什么注意事项?5.如何通过软引用实现一个简单的缓存?</think>### JavaWeakReferenceSoftReference的区别及使用场景 #### 核心区别 1. **垃圾回收行为** - **软引用(SoftReference)**:仅在内存不足时被回收(JVM抛出`OutOfMemoryError`前) 垃圾回收逻辑:`可用内存 < 当前堆大小 * -Xmx比例`(默认70%)时触发回收[^1] - **弱引用(WeakReference)**:**无论内存是否充足**,只要发生GC就会被回收 $$ \text{回收条件}:\ \text{GC触发} \ \land \ \neg \exists \ \text{强引用} $$ 2. **引用强度排序** $$ \text{强引用} > \text{软引用} > \text{弱引用} > \text{虚引用} $$ - 强引用:`Object obj = new Object()` - 弱引用:`WeakReference<Object> ref = new WeakReference<>(obj)` 3. **典型使用场景** | 引用类型 | 适用场景 | 示例 | |----------------|-----------------------------------|--------------------------| | **SoftReference** | 内存敏感缓存 | 图片缓存、临时计算结果 | | **WeakReference** | 防止内存泄漏的辅助数据结构 | `WeakHashMap`键引用、监听器 | #### 代码示例对比 ```java // 软引用示例:缓存实现 SoftReference<BigData> cache = new SoftReference<>(loadBigData()); if (cache.get() != null) { // 内存充足时可用 process(cache.get()); } else { // 内存不足时自动清除 reloadCache(); } // 弱引用示例:防止内存泄漏 WeakReference<EventListener> listenerRef = new WeakReference<>(new EventListener()); eventBus.register(listenerRef.get()); // GC后自动解除绑定 ``` #### 引用队列(ReferenceQueue)机制 ```mermaid graph LR A[对象被回收] --> B[引用入队] B --> C[执行清理操作] ``` 典型应用: ```java ReferenceQueue<Object> queue = new ReferenceQueue<>(); WeakReference<Object> ref = new WeakReference<>(new Object(), queue); // 监控回收状态 Reference<?> clearedRef = queue.remove(); // 阻塞直到有引用入队 System.out.println("对象已被回收: " + clearedRef); ``` #### 关键注意事项 1. **软引用可能导致缓存雪崩** 内存不足时集中回收所有软引用对象,需设计回源机制 2. **弱引用不保证存活时间** 对象可能在任何GC周期被回收,需做空值检查 3. **Android系统差异** Android 2.3+ 中软引用回收策略更激进(优先于弱引用回收)[^2] > 实践建议:优先考虑`WeakHashMap`或`ConcurrentHashMap`+弱引用方案,而非直接使用`SoftReference`实现缓存[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值