java中的四种引用

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 TypeMethod 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.

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值