java中的四种引用

来源:互联网 发布:centos更新命令 编辑:程序博客网 时间:2024/06/05 22:47

  • 快速理解java的四种引用
    • 1 强引用
    • 2 弱引用
    • 3 软引用
    • 4 虚引用
  • Reference抽象类
  • 参考资料

1. 快速理解java的四种引用

1.1 强引用

  • 强引用就是通常用到的引用,它是如此之强,以至于JVM宁可抛出OOM异常(内存溢出)也不愿回收它们。
Object obj = new Obeject();

1.2 弱引用

  • 弱引用可以帮你拿到强引用已不可达,但未被垃圾回收标记的对象,弱引用并不影响这些对象的生命周期。
    @Test    public void testWeakReference(){        Object obj = new Object();        WeakReference<Object> weakReference = new WeakReference<Object>(obj);        obj = null; //通过弱引用拿到        Assert.assertNotNull(weakReference.get());        System.gc();//弱引用无论内存是否充足,都会被gc回收        Assert.assertNull(weakReference.get());    }

1.3 软引用

  • 软引用和弱引用的区别在于,软引用可达的对象只有在JVM内存不足时才会被回收,简单地说,它可以一定程度上影响对象的生命周期。
  • 软引用常常被用于缓存。
    @Test    public void testSoftReference() {        Object obj = new Object();        SoftReference<Object> softReference = new SoftReference<Object>(obj);        obj = null;        Assert.assertNotNull(softReference.get());        System.gc();        Assert.assertNotNull(softReference.get());    }

1.4 虚引用

  • 无法通过虚引用拿到对象,但虚引用只有在对象完全被移出内存时才会加入到引用队列。
  • 虚引用允许你知道具体何时其引用的对象从内存中移除,而实际上这是Java中唯一的方式,通过虚引用来执行析构动作比重写finalize方法更加安全高效(一个重写了finalize方法的对象如果想要被回收掉,需要经历两个单独的垃圾收集周期,更糟的是,理论上,这个即将被回收的对象是可以在一个不符合规范的析构方法里面重新复活)
    private static final class ObjectOverrideFinalize {        @Override        protected void finalize() throws Throwable {            super.finalize();            System.out.println("finalize method executed");        }    }    @Test    public void testPhantomReference() throws InterruptedException{        ObjectOverrideFinalize obj = new ObjectOverrideFinalize();        WeakReference<ObjectOverrideFinalize> weakReference = new WeakReference<ReferencesTest.ObjectOverrideFinalize>(obj);        ReferenceQueue<ObjectOverrideFinalize> q = new ReferenceQueue<>();        PhantomReference<ObjectOverrideFinalize> phantomReference = new PhantomReference<>(obj, q);        obj=null;        //1.此时弱引用仍然可以拿到对象        Assert.assertNotNull(weakReference.get());        //2.第一次gc,由于重写了finalize方法,因此在这次gc中该对象只是被标记,而内存不会被回收        System.gc();        Thread.sleep(500);        Assert.assertNull(weakReference.get());//由于已被标记,因此弱引用已经无法拿到对象        //由于内存未被回收,因此虚引用并未被加入队列        Assert.assertFalse(phantomReference.isEnqueued());        Assert.assertNull(q.poll());        //3.第二次gc,对象内存被回收        System.gc();        Thread.sleep(500);        Assert.assertNull(weakReference.get());        //对象内存被回收,虚引用加入队列        Assert.assertTrue(phantomReference.isEnqueued());        Assert.assertNotNull(q.poll());    }

2. Reference抽象类

  • java的三种引用(弱引用,软引用,虚引用)都继承自该抽象类;
  • 由于Reference和垃圾收集密切相关,因此并不建议用户自行扩展抽象类。
Modifier and Type Method and Description void clear() Clears this reference object. boolean enqueue() Adds this reference object to the queue with which it is registered, if any. T get() Returns this reference object’s referent. boolean isEnqueued() Tells whether or not this reference object has been enqueued, either by the program or by the garbage collector.

参考资料

  • 理解java引用
  • 深入理解Java虚拟机
原创粉丝点击