WeakReference与SoftReference

WeakReference与SoftReference都可以用来保存对象的实例引用,这两个类与垃圾回收有关。

WeakReference是弱引用,其中保存的对象实例可以被GC回收掉。这个类通常用于在某处保存对象引用,而又不干扰该对象被GC回收,通常用于Debug、内存监视工具等程序中。因为这类程序一般要求即要观察到对象,又不能影响该对象正常的GC过程。

最近在JDK的Proxy类的实现代码中也发现了Weakrefrence的应用,Proxy会把动态生成的Class实例暂存于一个由Weakrefrence构成的Map中作为Cache。


SoftReference是强引用,它保存的对象实例,除非JVM即将OutOfMemory,否则不会被GC回收。这个特性使得它特别适合设计对象Cache。对于Cache,我们希望被缓存的对象最好始终常驻内存,但是如果JVM内存吃紧,为了不发生OutOfMemoryError导致系统崩溃,必要的时候也允许JVM回收Cache的内存,待后续合适的时机再把数据重新Load到Cache中。这样可以系统设计得更具弹性。

 

WeakReference的一个测试程序:

 

import java.lang.ref.WeakReference;

public class WeakReferenceTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        A a = new A();
        a.str = "Hello, reference";
        WeakReference<A> weak = new WeakReference<A>(a);
        a = null;
        int i = 0;
        while (weak.get() != null) {
            System.out.println(String.format("Get str from object of WeakReference: %s, count: %d", weak.get().str, ++i));
            if (i % 10 == 0) {
                System.gc();
                System.out.println("System.gc() was invoked!");
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {

            }
        }
        System.out.println("object a was cleared by JVM!");
    }

}

 程序运行结果:

Get str from object of WeakReference: Hello, reference, count: 1
Get str from object of WeakReference: Hello, reference, count: 2
Get str from object of WeakReference: Hello, reference, count: 3
Get str from object of WeakReference: Hello, reference, count: 4
Get str from object of WeakReference: Hello, reference, count: 5
Get str from object of WeakReference: Hello, reference, count: 6
Get str from object of WeakReference: Hello, reference, count: 7
Get str from object of WeakReference: Hello, reference, count: 8
Get str from object of WeakReference: Hello, reference, count: 9
Get str from object of WeakReference: Hello, reference, count: 10
System.gc() was invoked!
object a was cleared by JVM!

 

SoftReference的一个测试程序:

import java.lang.ref.SoftReference;

public class SoftReferenceTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        A a = new A();
        a.str = "Hello, reference";
        SoftReference<A> sr = new SoftReference<A>(a);
        a = null;
        int i = 0;
        while (sr.get() != null) {
            System.out.println(String.format("Get str from object of SoftReference: %s, count: %d", sr.get().str, ++i));
            if (i % 10 == 0) {
                System.gc();
                System.out.println("System.gc() was invoked!");
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {

            }
        }
        System.out.println("object a was cleared by JVM!");
    }

}

 程序运行结果:

  1. Get str from object of SoftReference: Hello, reference, count: 1  
  2. Get str from object of SoftReference: Hello, reference, count: 2  
  3. Get str from object of SoftReference: Hello, reference, count: 3  
  4. Get str from object of SoftReference: Hello, reference, count: 4  
  5. Get str from object of SoftReference: Hello, reference, count: 5  
  6. Get str from object of SoftReference: Hello, reference, count: 6  
  7. Get str from object of SoftReference: Hello, reference, count: 7  
  8. Get str from object of SoftReference: Hello, reference, count: 8  
  9. Get str from object of SoftReference: Hello, reference, count: 9  
  10. Get str from object of SoftReference: Hello, reference, count: 10  
  11. System.gc() was invoked!   
  12. Get str from object of SoftReference: Hello, reference, count: 11  
  13. Get str from object of SoftReference: Hello, reference, count: 12  
  14. Get str from object of SoftReference: Hello, reference, count: 13  
  15. Get str from object of SoftReference: Hello, reference, count: 14  
  16. Get str from object of SoftReference: Hello, reference, count: 15  
  17. Get str from object of SoftReference: Hello, reference, count: 16  
  18. Get str from object of SoftReference: Hello, reference, count: 17  
  19. Get str from object of SoftReference: Hello, reference, count: 18  
  20. Get str from object of SoftReference: Hello, reference, count: 19  
  21. Get str from object of SoftReference: Hello, reference, count: 20  
  22. System.gc() was invoked!   
  23. Get str from object of SoftReference: Hello, reference, count: 21  
  24. Get str from object of SoftReference: Hello, reference, count: 22  
  25. Get str from object of SoftReference: Hello, reference, count: 23  
  26. Get str from object of SoftReference: Hello, reference, count: 24  
  27. Get str from object of SoftReference: Hello, reference, count: 25  
  28. Get str from object of SoftReference: Hello, reference, count: 26  
  29. Get str from object of SoftReference: Hello, reference, count: 27  
  30. Get str from object of SoftReference: Hello, reference, count: 28  
自己的标注 写道
上面的打印结果会一直持续下去。 因为soft.get()一直不会为空

SoftReference比WeakReference生命力更强,当JVM的内存不吃紧时,即使引用的对象被置为空了,Soft还可以保留对该对象的引用,此时的JVM内存池实际上还保有原来对象,只有当内存吃紧的情况下JVM才会清除Soft的引用对象,并且会在未来重新加载该引用的对象。

而WeakReference则当清理内存池时会自动清理掉引用的对象。

 

 

 

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

 java.lang.ref.WeakReference

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

  A obj = new A();

    WeakReference wr = new WeakReference(obj);

    obj = null;

    //等待一段时间,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);

    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值