Java四大引用类型

121 阅读1分钟

类图

image.png

Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。

强引用

默认支持模式。最常见的普通对象引用 强引用的对象,出现OOM都不会对该对象进行回收。如果没有其他引用关系,只要超过引用的作用域或显示地将强引用赋值null,一般认为可以被垃圾收集(具体回收时机还要看垃圾收集策略)

public class Demo1 {
    
    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        System.out.println("-----gc before: "+myObject);

        myObject = null;
        
        System.gc();
        
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }

        System.out.println("-----gc after: "+myObject);
    }
    
}

软引用

当系统内存充足时软引用对象不会被回收,当系统内存不足时软引用对象被回收。常用在对内存敏感的程序中,比如高速缓存,内存够用的时候就保留,不够用就回收!

public class Demo1 {

    public static void main(String[] args)
    {
        //当我们内存不够用的时候,soft会被回收的情况,设置我们的内存大小:-Xms10m -Xmx10m
        SoftReference<MyObject> softReference = new SoftReference<>(new MyObject());

        System.gc();
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("-----gc after内存够用: "+softReference.get());

        try
        {
            byte[] bytes = new byte[8 * 1024 * 1024];
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println("-----gc after内存不够: "+softReference.get());
        }
    }
}

应用场景

假如有一个应用需要读取大量的本地图片:

  • 如果每次读取图片都从硬盘读取则会严重影响性能,
  • 如果一次性全部加载到内存中又可能造成内存溢出。

此时使用软引用可以解决这个问题。 设计思路是:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题。

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

弱引用

当有垃圾回收机制一运行,弱引用对象就会被回收。

public class Demo1 {

    public static void main(String[] args)
    {
        WeakReference<MyObject> weakReference = new WeakReference<>(new MyObject());
        System.out.println("-----gc before内存够用: " + weakReference.get());

        System.gc();
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }

        System.out.println("-----gc after内存够用: " + weakReference.get());
    }
}

虚引用

在任何时候都可以被垃圾器回收。