java中强引用、弱引用、软引用、虚引用学习

文章目录

  • 强引用
  • 弱引用
  • 软引用
  • 虚引用

将引用之前首先让我们一起回顾一下
java对象的生命周期

强引用

在实际开发场景中,我们一般使用的都是强引用,只要强引用存在,垃圾回收即使OOM也不会回收,知道强引用释放以后,对象才会被释放掉,可以显示地将引用赋值为null,这样的话,JVM会在合适的时间回收该对象。

以下是测试:

    public void method() {
        Object o = new Object();
        Object[] os = new Object[800000];
        System.out.println(os.length);
    }


    @Test
    public void srongReference(){
        method();
    }

在method方法没有结束之前,method中定义的局部变量的对象是不会被回收,method结束后会在适合GC。

回收测试:

    @Test
    public void strongReference() throws InterruptedException {
        Thread.sleep(40 * 1000);
        System.out.println("加载");
        method();
        Object o = new Object();
        Object[] os = new Object[800000];
        System.out.println("判断是否回收");
        Thread.sleep(20 * 1000);
        o = null;
        os = null;
        System.gc();
        System.out.println("强制回收");
        Thread.sleep(100 * 1000);
    }

通过 jconsole监控内存变化,发现当强引用关系解除以后,强制GC的时候,对象会被回收掉!!!
java中强引用、弱引用、软引用、虚引用学习_第1张图片

弱引用

引用是用来描述非必须对象的,当JVM进行垃圾回收时候,无论内存是否充足,都会回收。

    @Test
    public void weakReference() {
//        ArrayList ps = new ArrayList<>();//list存储的对象引用也是强引用关系
//        ps.add(person);
        WeakReference<Object> wf = new WeakReference<>(new Person("weijie", 25));
        System.out.println(wf.get());
        System.out.println(wf.isEnqueued());
        System.gc();
        System.out.println(wf.get());
        System.out.println(wf.isEnqueued());
    }

java中强引用、弱引用、软引用、虚引用学习_第2张图片
由控制台输可以看出,只要是弱引用,只要发生GC对象会被回收。

    @Test
    public void weakReference() {
        Person person = new Person("weijie", 25);
        ArrayList<Person> ps = new ArrayList<>();//list存储的对象引用也是强引用关系
        ps.add(person);
        WeakReference<Object> wf = new WeakReference<>(person);
        System.out.println(wf.get());
        System.out.println(wf.isEnqueued());
        System.gc();
        System.out.println(wf.get());
        System.out.println(wf.isEnqueued());
    }

java中强引用、弱引用、软引用、虚引用学习_第3张图片
由上可看出由于list导致对象存在强引用关系,此时加上弱引用的话对象也不会被回收,需要手动将person=null 接触强引用关系以后,对象才会GC时候回收

软引用

用来描述一些有用但并不是必须的对象,对于软引用关联的对象,只有在内存不足的时候JVM才会回收该对象,这一点可以很好解决OOM问题,这个特性很适合用来实现缓存:网页缓存、图片缓存等。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中。

    @Test
    public void softReference() {
        SoftReferenceCache<Integer, Person> referenceCache = new SoftReferenceCache<>();
        referenceCache.put(0, new Person("weijie", 24));
        System.gc();
        System.out.println(referenceCache.get(0));
    }

java中强引用、弱引用、软引用、虚引用学习_第4张图片

虚引用

虚引用:垃圾回收时回收,无法通过引用取到对象值PhantomReference 唯一的用处就是跟踪 referent 何时被 enqueue(入队列) 到 ReferenceQueue 中虚引用主要用来跟踪对象被垃圾回收的活动

虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用, 来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列, 那么就可以在所引用的对象的内存被回收之前采取必要的行动

    @Test
    public void phantomReference(){
        Person person = new Person("weijie", 24);
        ReferenceQueue<Person> referenceQueue = new ReferenceQueue<Person>();
        PhantomReference<Person> personPhantomReference = new PhantomReference<Person>(person, referenceQueue);
        System.out.println(referenceQueue.poll());
        System.out.println(personPhantomReference.get());
        //判断对象是否被标记回收
        System.out.println(personPhantomReference.enqueue());
        person = null;
        System.out.println(personPhantomReference.get());
        System.out.println(personPhantomReference.enqueue());
    }

java中强引用、弱引用、软引用、虚引用学习_第5张图片
虚引用打印的值永远为null,唯一用处就是显示enqueue(入队列)

你可能感兴趣的:(Java,#,基础,每日学习)