美文网首页
Java引用类型之 :虚引用

Java引用类型之 :虚引用

作者: 贪睡的企鹅 | 来源:发表于2019-07-15 13:03 被阅读0次

    1 简述

    虚引用是使用PhantomReference创建的引用,虚引用也称为幽灵引用或者幻影引用,是所有引用类型中最弱的一个。如果一个对象与GC Roots之间仅存在虚引用,
    则称这个对象为虚可达(phantom reachable)对象,一个对象是否有虚引用的存在,
    完全不会对其生命周期构成影响,也无法通过虚引用获得一个对象实例。

    2 使用

    2.1 创建弱引用
    
    //创建一个强引用变量s,将对象地址设置给变量s这个引用
    String s = new String("Frank");  
    
    //创建一个Reference对象phantomRef,将对象地址设置给phantomRef.reference引用
    PhantomReference  phantomRef = new PhantomReference<String>(s); 
    
    //强引用不在指向new String("Frank"),此时new String("Frank")为弱可达对象
    s = null; 
    

    这里new PhantomReference()本身也是堆中对象。指向对象地址的是其内部属性变量reference,在这里我把他称为引用,由于是PhantomReference创建引用所以我们把它称为虚引用

    image

    referenceQueue队列

    ReferenceQueue<T> referenceQueue = new ReferenceQueue<>();
    //创建一个Reference对象phantomRef2,将对象地址设置给phantomRef2.reference引用
    //同时给softRef2设置referenceQueue
    PhantomReference<Object> phantomRef2 = new PhantomReference<>(new Object(),referenceQueue);
    

    当引用对象new Object()将被回收时,会将reference对象放置进referenceQueue队列中。通过监控这个队列,取出reference对象,就可以对reference对象(存在堆中被phantomRef2引用)进行清理工作。

    image
    2.2 释放弱引用
    phantomRef2.clear();
    

    3 WeakReference 源码

    WeakReference源码可以说非常少,其功能基本继承至父类Reference

    public class PhantomReference<T> extends Reference<T> {
    
        public T get() {
            return null;
        }
    
        public PhantomReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    
    }
    

    案例

    虚引用基本时用来和ReferenceQueue联合使用监听某个对象的回收时机

    /**
     * -verbose:gc -Xms4m -Xmx4m -Xmn2m
     * 虚引用基本时用来和ReferenceQueue联合使用监听某个对象的回收时机
     */
    public class PhantomReferenceTest {
        private static final List<Object> TEST_DATA = new LinkedList<>();
        private static final ReferenceQueue<TestClass> QUEUE = new ReferenceQueue<>();
    
        public static void main(String[] args) {
            /** 监听new TestClass("Test")对象回收时机  **/
            PhantomReference<TestClass> phantomReference = new PhantomReference<>(new TestClass("Test"), QUEUE);
    
            // 该线程不断读取这个虚引用,并不断往列表里插入数据,以促使系统早点进行GC
            new Thread(() -> {
                while (true) {
                    TEST_DATA.add(new byte[1024 * 100]);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        Thread.currentThread().interrupt();
                    }
                    System.out.println(phantomReference.get());
                }
            }).start();
    
            // 这个线程不断读取引用队列,当弱引用指向的对象呗回收时,该引用就会被加入到引用队列中
            new Thread(() -> {
                while (true) {
                    Reference<? extends TestClass> poll = QUEUE.poll();
                    if (poll != null) {
                        System.out.println("--- 虚引用对象被jvm回收了 ---- " + poll);
                        System.out.println("--- 回收对象 ---- " + poll.get());
                    }
                }
            }).start();
    
    
            try {
                Thread.currentThread().join();
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    
        static class TestClass {
            private String name;
    
            public TestClass(String name) {
                this.name = name;
            }
    
            @Override
            public String toString() {
                return "TestClass - " + name;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Java引用类型之 :虚引用

          本文链接:https://www.haomeiwen.com/subject/zpqnkctx.html