强引用、软引用、弱引用、虚引用

强引用、软引用、弱引用、虚引用

        • 1.前景提示
        • 2.整体介绍
        • 3.详细介绍

1.前景提示

  • 要搞明白强、软、弱、虚这四种引用之前需要对JVM GC垃圾回收知识有所了解
  • 可见:【JVM】JVM内存结构+JVM参数配置+GC垃圾回收+OOM内存溢出

2.整体介绍

  • 打开JDK文档
    强引用、软引用、弱引用、虚引用_第1张图片
  • 可以看到Reference下面有三个子类:SoftReference软引用,WeakReference弱引用,PhantomReference虚引用
  • 也可以用idea打开类图来看他们之间的关系:
    强引用、软引用、弱引用、虚引用_第2张图片

3.详细介绍

3.1 强引用

  • 强引用就是我们平常创建对象实例的方式,比如:Object obj = new Objict(); obj就是强引用
  • 其实所谓强软弱虚,都是相对于JVM垃圾回收来说的
  • 强引用在面对JVM垃圾回收时,具体如下:
    强引用、软引用、弱引用、虚引用_第3张图片
  • 下面我们写个Demo:
    强引用、软引用、弱引用、虚引用_第4张图片
  • 这个Demo很简单,创建一个对象,让obj1指向它,然后再把obj1对obj2进行引用赋值。
  • 最后把obj1置空,开启GC垃圾回收,打印obj2
  • 运行结果:
    强引用、软引用、弱引用、虚引用_第5张图片
  • obj2还是好好的指向对象实例,这个Demo其实没什么值得说的,把它贴出来也只是跟后面的其他引用做对比

3.2 软引用

  • 软引用是一种相对于强引用弱化了一些的引用,需要用java.lang.ref.SoftRefrtence来实现。
  • 对于只有软引用的对象来说:

1,当系统内存充足时它不会被回收。

2,当系统内存不足时它会被回收。

  • Demo:
/**
 * 软引用Demo
 * 1.软引用在内存够用时不回收,不够用的时候回收
 * 2.demo正常时候运行
 * 3.在配置-Xms5m -Xmx5m -XX:+PrintGCDetails下运行
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/4
 */
public class SoftReferencrDemo {
    public static void main(String[] args) {

        Object obj1 = new Object();
        SoftReference softReference = new SoftReference<>(obj1);

        System.out.println(obj1);
        System.out.println(softReference.get());

        obj1 = null;
        System.gc();

        try {

            byte[] b = new byte[10 * 1024 * 1024];
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println(obj1);
            System.out.println(softReference.get());
        }

    }
}
 
  
  • 内存充足时运行结果:
    强引用、软引用、弱引用、虚引用_第6张图片
  • 在配置-Xms5m -Xmx5m -XX:+PrintGCDetails下,内存不足时运行结果:
  • 软引用通常用在对内存敏感的程序中,比如高速缓存就有用到软引用,内存够用的时候就保留,不高用就回收!

3.3 弱引用

  • 弱引用需要用java.lang.ref.WeakReference来实现,它比软引用的生存期更短。
  • 对于只有弱引用的对象来说,只要垃圾回收一运行,不管JVM的内存是否足够,都会回收该对象。
  • Demo:
/**
 * 弱引用
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/4
 */
public class WeakReferenceDemo {
    public static void main(String[] args) {
        Object obj = new Object();
        WeakReference weakReference = new WeakReference<>(obj);

        System.out.println(obj);
        System.out.println(weakReference.get());

        obj = null;
        System.gc();

        System.out.println(obj);
        System.out.println(weakReference.get());
    }
}
 
  
  • 运行结果:
    强引用、软引用、弱引用、虚引用_第7张图片
    -弱引用的使用场景:
    强引用、软引用、弱引用、虚引用_第8张图片
    3.3.1 WeakHashMap
    -WeakHashMap是一种弱引用map,内部的key会存储为弱引用,当jvm gc的时候,如果这些key没有强引用存在的话,会被gc回收掉
    -Demo:

/**
 * todo
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/4
 */
public class WeakHashMapDemo {
    public static void main(String[] args) {

        myHashMap();
        System.out.println("========================");
        myWeakHashMap();
    }
    private static void myHashMap(){
        HashMap weakHashMap = new HashMap<>();
        Integer key = new Integer(1);
        String value = "test";
        weakHashMap.put(key,value);
        System.out.println(weakHashMap);
        key = null;

        System.out.println(weakHashMap);
        System.gc();
        System.out.println(weakHashMap+"\t"+weakHashMap.size());
    }

    private static void myWeakHashMap(){
        WeakHashMap weakHashMap = new WeakHashMap<>();
        Integer key = new Integer(1);
        String value = "test";
        weakHashMap.put(key,value);
        System.out.println(weakHashMap);
        key = null;

        System.out.println(weakHashMap);
        System.gc();
        System.out.println(weakHashMap+"\t"+weakHashMap.size());
    }
}

  • 运行结果:
    强引用、软引用、弱引用、虚引用_第9张图片
  • WeakHashmap业务场景就是缓存,可以有效的节省内存,缓存丢失也不会出太大问题,可以再次获取。许多开源框架,例如tomcat等都使用了weakHashmap做为缓存处理。

3.4 虚引用

  • 虚引用需要java.lang.ref.PhantomReference来实现,至于它到底是个什么东西:
    强引用、软引用、弱引用、虚引用_第10张图片
  • 至于引用队列ReferenceQueue:
    强引用、软引用、弱引用、虚引用_第11张图片
  • Demo:
/**
 * 虚引用
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/4
 */
public class PhantomReferenceDemo {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        ReferenceQueue referenceQueue = new ReferenceQueue<>();
        PhantomReference phantomReference = new PhantomReference<>(obj,referenceQueue);

        System.out.println(obj);
        System.out.println(phantomReference.get());
        System.out.println(referenceQueue.poll());

        System.out.println("=====================");

        obj = null;
        System.gc();
        Thread.sleep(500);
        System.out.println(obj);
        System.out.println(phantomReference.get());
        System.out.println(referenceQueue.poll());

    }
}

 
  
  • 运行结果:
    强引用、软引用、弱引用、虚引用_第12张图片
  • 可以看到虚引用phantomReference.get()无论在垃圾回收前还是回收后都null;
  • 反而是引用队列,在gc垃圾回收后把虚引用的对象保存了下来。
  • 总结:
    强引用、软引用、弱引用、虚引用_第13张图片
    【完】
    注:文章内所有测试用例源码:https://gitee.com/wjie2018/test-case.git

你可能感兴趣的:(java,JVM)