代码改变世界

Strong/Soft/Weak/Phantom

2011-12-14 16:46  康杜  阅读(402)  评论(0编辑  收藏  举报

Strong Reference 强引用

在我们的代码里,这样的引用是强引用。

StringBuffer buffer = new StringBuffer();

那么什么时候强引用太强了呢,导致它引用的对象无法被清除,最后导致内存溢出(OutOfMemoryError)。我们来看一个缓存的例子。

例子1,

public class ReferenceTest {
    //private Map map = new WeakHashMap();

    //Strong Reference Map
    private Map map = new HashMap();
   
    @Before
    public void setup() throws IOException{
        for(int i=0 ; i <10 ; i++) {
            BufferedImage img = ImageIO.read(new File("D:\\Lenovo4-2.jpg"));
            map.put("img"+i, img);
        }
    }
   
    @Test
    public void getFromMap(){
        new Thread(){
            public void run(){
                int i = 0;
                while(i<10) {
                    i ++;
                    Object o = map.get("img"+1);
                    System.out.println(o);
                }
            }
        }.start();
    }
}

 

以上的程序在vm 参数-Xmx20m时运行出现OutOfMemoryError, 但是把HashMap换成WeakMap的时候就不会出现这种情况。

出现以上这种情况的原因是,当使用强引用的时候JVM不能够回收map引用的对象。

但是WeakMap不一样,以上例子中由于map对象已经被回收,同时map里的对象都是弱引用(WeakReference), map中的对象也被回收。

 

Soft Reference 软引用

SoftReference的引用强度比WeakReference强一些,它不是那种要么全有,要么全无的引用。软引用的对象会不会被垃圾回收决定于JVM内存在使用情况。我们把大数据放在列表中,比如

http://www.ibm.com/developerworks/java/library/j-jtp01246/index.html

例子2,

public class SoftReferenceTest {
    private List<BufferedImage> imgs;

    @Before
    public void setup() throws IOException {
        imgs = new ArrayList<BufferedImage>();
        for (int i=0; i< 10; i++) {
            BufferedImage img = ImageIO.read(new File("D:\\Lenovo4-2.jpg"));
            imgs.add(img);
        }
    }

    @Test
    public void getSoftReferedObject() {
        for (BufferedImage img : imgs){
            System.out.println(img);
        }
    }
}

以上的代码在VM参数为-Xmx20m的情况下出现OutOfMemoryError,但是换成以下代码就不会

public class SoftReferenceTest {

    private List<SoftReference<BufferedImage>> imgs;

    @Before
    public void setup() throws IOException {
        imgs = new ArrayList<SoftReference<BufferedImage>>();
        for (int i=0; i< 10; i++) {
            SoftReference<BufferedImage> img = new SoftReference<BufferedImage>(ImageIO.read(new File("D:\\Lenovo4-2.jpg")));
            imgs.add(img);
        }
    }

    @Test
    public void getSoftReferedObject() {
        for (SoftReference<BufferedImage> img : imgs){
            System.out.println(img.get());
        }
    }

}

我们在用SoftReference的时候要判断引用的对象是不是空。

Weak Reference 弱引用

http://www.ibm.com/developerworks/java/library/j-jtp11225/index.html

上面的例子1 WeakHashMap是WeakReference的一个应用。

 

Phantomo Reference 幻影引用

幻影引用又区别与软引用和弱引用。我们甚至 不能像SoftReference或者WeakReference一样通过get方法得到被引用对象--调用get方法永远返回空。幻影引用的作用在于:第一能够通过它判断一个对象已经被垃圾回收;第二,避免重写finalize方法以复活对象时,为这些对象创建强引用。

 

Java区分引用(Strong,Soft,Weak,Phathom)有什么用?

让垃圾回收器更好地管理内存,防止潜在的内存泄露。

 

Original explanation

http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html