2018-07-26 java 四种引用:强引用、软引用、弱引用

2018-07-26  本文已影响0人  _你好_

四种引用

  1. 强引用 (Strong Reference)
  2. 软引用 (Soft Reference)
  3. 弱引用 (Weak Reference)
  4. 虚引用 (Phantom Reference)
    以上引用强度依次变弱,从引用对象到gc root 节点的一条链路上引用强度以最弱的为准,多条链路的引用强度以最强的为准
1. 强引用 (Strong Reference)
Test test = new Test();

2. 软引用(Soft Reference)

特点:使用软引用包裹的对象,如果该对象的引用强度为软引用则会发生gc且内存不足时被回收

    @Test
    public void softReference() {
        byte[] bytes1 = new byte[1024 * 1024 * 128];
        SoftReference<byte[]> weakReference = new SoftReference<>(bytes1);

        assertSame(bytes1, weakReference.get());
        bytes1 = null;
        System.out.println("before gc");
        byte[] bytes2 = new byte[1024 * 1024 * 128];
        System.out.println("after gc");
        // 如果gc时内存不足
        assertNull(weakReference.get());
    }

增加启动参数

-Xmx256m -Xmn256m -XX:+PrintGCDetails  -XX:+PrintGCDateStamps 
企业微信截图_15326105016656.png

3 弱引用 (Weak Reference)

特点:使用弱引用包裹的对象,如果该对象的引用强度为弱引用则会在发生gc被回收

    @Test
    public void weakReference() {
        Object referent = new Object();
        WeakReference<Object> weakReference = new WeakReference<Object>(referent);
        assertSame(referent, weakReference.get());

        referent = null;
        System.gc();
        // 一旦没有指向 referent 的强引用, weak reference 在 GC 后会被自动回收
        assertNull(weakReference.get());
    }

虚应用 (Phantom Reference)

虚引用是最有意思的一个
其无论在任何适合 调用 get 方法获取到的对象都是 null
他不像软引用、弱引用会自动回收内存,虚引用的存在更倾向于发送通知,虚引用被确定可以回收时将自己放入到 Reference 的 pending list 中。
次数 ReferenceHandler 线程发现 pending list 中存在对象,则执行该对象的清理方法。等到下次gc时将该对象移除。

以下代码为网上获取到的

public static void main(String[] args) throws Exception {
        ReferenceQueue<Test> queue = new ReferenceQueue<>();
        Thread moniterThread = new Thread(() -> {
            // 监视线程,随时检查引用队列,一旦发现引用就会打印出来
            for (; ; ) {
                Reference<? extends Test> ref = queue.poll();
                if (ref != null) {
                    System.out.printf("%s加入引用队列%n", ref.getClass().getSimpleName());
                }
                try {
                    Thread.sleep(0);
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
        moniterThread.start();
        Test test = new Test();
        WeakReference<Test> weakReference = new WeakReference<Test>(test, queue);
        PhantomReference<Test> phantomReference = new PhantomReference<Test>(test, queue);
        // 去除强引用
        test = null;
        System.out.println(">> 第一次gc <<");
        System.gc();
        // 这里等待一段时间,保证引用进入队列,和finalize()方法执行
        Thread.sleep(100);
        System.out.println("\n>> 第二次gc <<");
        System.gc();
        assert weakReference != null && phantomReference != null;
        moniterThread.interrupt();
    }

    public static class Test {
        @Override
        protected void finalize() throws Throwable {
            System.out.println("== finalize() ==");
        }
    }

程序执行情况如下


企业微信截图_1532611346661.png

该博客该出的解释为

1532611446(1).png

那么this逃逸呢?

public class PhantomReferenceSaveOneselfTest {
    static volatile Test test = new Test();

    public static void main(String[] args) throws Exception {
        ReferenceQueue<Test> queue = new ReferenceQueue<>();
        Thread monitorThread = new Thread(() -> {
            // 监视线程,随时检查引用队列,一旦发现引用就会打印出来
            for (; ; ) {
                Reference<? extends Test> ref = queue.poll();
                if (ref != null) {
                    System.out.printf("%s 加入引用队列%n", ref.getClass().getSimpleName());
                }
                try {
                    Thread.sleep(0);
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
        monitorThread.start();
        PhantomReference<Test> phantomReference = new PhantomReference<Test>(test, queue);
        // 去除强引用
        test = null;
        System.out.println(">> 第一次gc <<");
        System.gc();
        // 这里等待一段时间,保证引用进入队列,和finalize()方法执行
        Thread.sleep(100);
        System.out.println("\n>> 第二次gc <<");
        System.gc();

        Thread.sleep(100);
        test = null;
        System.out.println("\n>> 第三次gc <<");
        System.gc();

        Thread.sleep(100);
        assert phantomReference != null;
        monitorThread.interrupt();
    }

    public static class Test {
        private byte[] bytes = new byte[1024 * 1024 * 2];
        @Override
        protected void finalize() throws Throwable {
            System.out.println("== finalize() ==");
            test = this;
        }
    }
}
企业微信截图_15326119672211.png
上一篇下一篇

猜你喜欢

热点阅读