Java强引用,软引用,弱引用与虚引用

目录

          • 1 概述
          • 2 强引用(StrongReference)
          • 3 软引用(SoftReference)
          • 4 弱引用(WeakReference)
          • 5 虚引用(PhantomReference)

参考资料 深入理解

1 概述
引用类型 被回收时间 用途 生存时间
强引用 从来不会 对象的一般状态 JVM停止运行时
软引用 内存不足时 对象缓存 内存不足时
弱引用 JVM垃圾回收时 对象缓存 GC运行后
虚引用 未知 未知 未知
2 强引用(StrongReference)

开发中,定义的引用一般都是强引用,这是最普遍的使用。如果一个对象具有强引用,就是必不可少的对象,不会被垃圾回收器回收。
当内存空间不足时,JVM宁愿抛出OOM异常,使程序终止,也不回收这种引用

// object和str 都是强引用
Object object = new Object();
String str = "123";

如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为 null,  这样,JVM 会在合适的时间回收该对象。
ArrayList类的 clear()方法,就是通过将引用赋值为 null,来实现清理工作的。

public void clear(){
    modCount++;
    // Let gc do its work
    for(int i=0; i<size;i++)
      elementData[i] = null;
    
    size = 0;
}

在ArrayList类中定义了一个私有的变量elementData数组,在调用方法清空数组时可以看到为每个数组内容赋值为null。不同于elementData=null,强引用仍然存在,避免在后续调用 add()等方法添加元素时进行重新的内存分配。使用如clear()方法中释放内存的方法对数组中存放的引用类型特别适用,这样就可以及时释放内存。

3 软引用(SoftReference)

软引用,弱引用都可以和一个引用队列(ReferenceQueue)联合使用,虚引用必须和引用队列联合使用。在实际开发中,软引用最常用,弱引用和虚引用很少使用

ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new  PhantomReference<String>(new String("hello"), queue);

软引用是用来描述一些有用但不是必需的对象,在 Java中用 java.lang.ref.SoftReference类来表示。
对于软引用关联着的对象,只有在内存不足的时候,JVM才会回收该对象。因此,这一点可以很好地用来解决OOM的问题,并且这个特性,很适合用来实现缓存:比如网页缓存,图片缓存等。

如何利用软引用和弱引用解决OOM问题
假如有一个应用需要读取大量的本地图片。如果每次读取图片都从硬盘读取,会严重影响性能;但是如果全部加载到内存中,有可能造成内存溢出。此时,使用软引用可以解决这个问题。


设计思路
用一个 HashMap 来保存图片的路径 和 相应的图片对象 关联的软引用 之间的映射关系。
当内存不足时,JVM 会自动回收这些缓存图片对象,所占用的空间,从而有效的避免了 OOM问题
在 Android开发中,对于大量图片下载会经常用到

private Map<String, SoftReference<Bitmap>> imageCache = new
        HashMap<String,SoftReference<Bitmap>>();

public void addBitmapToCache(String path){
    // 强引用的 Bitmap对象
    Bitmap bitmap = BitmapFactory.decodeFile(path);
    // 软引用的 Bitmap对象
    SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);
    //添加该对象到 Map中 使其缓存
    imageCache.put(path,softBitmap);
}

public Bitmap getBitmapByPath(String path){
    // 从缓存中 取软引用的 Bitmap对象
    SoftReference<Bitmap> softBitmap = imageCache.get(path);
    // 判断 是否存在软引用
    if(softBitmap == null){
        return null;
    }
    // 取出 Bitmap对象,如果由于内存不足 Bitmap被回收,将取得空
    Bitmap bitmap = softBitmap.get();
    return bitmap;
}
4 弱引用(WeakReference)

弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用 java.lang.ref.WeakReference类来表示。
弱引用与软引用的区别:被软引用关联的对象只有在内存不足时才会被回收,而被弱引用关联的对象在JVM进行垃圾回收时总会被回收

只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。

使用场景

如果一个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么应该用 Weak Reference 来记住此对象。或者想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个对象的生命周期,这时候就应该用弱引用,这个引用不会在对象的垃圾回收判断中产生任何附加的影响。

5 虚引用(PhantomReference)
  • 虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期
  • 在任何时候都可能被垃圾回收器回收(对象与虚引用关联和不关联效果一样)
  • 虚引用主要用来跟踪对象被垃圾回收的活动
  • 虚引用必须和引用队列关联使用
  • 在 Java 中用 java.lang.ref.PhantomReference类 表示

你可能感兴趣的:(Java基础)