Java中的软引用,弱引用和虚引用

发表于:2012-2-01 09:23

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:sdtarena    来源:51Testing软件测试网采编

分享:

  弱引用

  当gc碰到弱可及对象,并释放abcWeakRef的引用,收集该对象。但是gc可能需要对此运用才能找到该弱可及对象。通过如下代码可以了明了的看出它的作用:

String abc=new String("abc");   
WeakReference<String> abcWeakRef = new WeakReference<String>(abc);   
abc=null;   
System.out.println("before gc: "+abcWeakRef.get());   
System.gc();   
System.out.println("after gc: "+abcWeakRef.get());  

  运行结果:

  before gc: abc
  after gc: null

  gc收集弱可及对象的执行过程和软可及一样,只是gc不会根据内存情况来决定是不是收集该对象。

  如果你希望能随时取得某对象的信息,但又不想影响此对象的垃圾收集,那么你应该用 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 这类的程序时常会用到,因为这类程序需要取得某对象的信息,但是不可以 影响此对象的垃圾收集。

  PhantomRefrence(虚引用)

  虚顾名思义就是没有的意思,建立虚引用之后通过get方法返回结果始终为null,通过源代码你会发现,虚引用通向会把引用的对象写进referent,只是get方法返回结果为null。先看一下和gc交互的过程在说一下他的作用。

  1 不把referent设置为null,直接把heap中的new String("abc")对象设置为可结束的(finalizable).

  2 与软引用和弱引用不同,先把PhantomRefrence对象添加到它的ReferenceQueue中,然后在释放虚可及的对象。

  你会发现在收集heap中的new String("abc")对象之前,你就可以做一些其他的事情。通过以下代码可以了解他的作用。

import java.lang.ref.PhantomReference;   
import java.lang.ref.Reference;   
import java.lang.ref.ReferenceQueue;   
import java.lang.reflect.Field;   
  
public class Test {   
    public static boolean isRun = true;   
  
    public static void main(String[] args) throws Exception {   
        String abc = new String("abc");   
        System.out.println(abc.getClass() + "@" + abc.hashCode());   
        final ReferenceQueue referenceQueue = new ReferenceQueue<String>();   
        new Thread() {   
            public void run() {   
                while (isRun) {   
                    Object o = referenceQueue.poll();   
                    if (o != null) {   
                        try {   
                            Field rereferent = Reference.class  
                                    .getDeclaredField("referent");   
                            rereferent.setAccessible(true);   
                            Object result = rereferent.get(o);   
                            System.out.println("gc will collect:"  
                                    + result.getClass() + "@"  
                                    + result.hashCode());   
                        } catch (Exception e) {   
  
                            e.printStackTrace();   
                        }   
                    }   
                }   
            }   
        }.start();   
        PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc,   
                referenceQueue);   
        abc = null;   
        Thread.currentThread().sleep(3000);   
        System.gc();   
        Thread.currentThread().sleep(3000);   
        isRun = false;   
    }   
  
}

  结果为:

  class java.lang.String@96354
  gc will collect:class java.lang.String@96354

22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号