zoukankan      html  css  js  c++  java
  • Java Reference引用 强引用 软引用 弱引用 虚引用

    1,强引用:

    package com.myjava.reference;
    /**
     * ①强引用不会被垃圾回收器自动回收
     * ②当内存空间不足时,Java虚拟机宁可抛出OutOfMemoryError错误,也不会随意回收强引用对象来解决内存不足问题
     * @author Administrator
     *
     */
    public class TestStrongReference {
    public static void main(String[] args) {
    Object ref = new Object();
    Object strongRef = ref;
    System.gc();
    System.out.println(strongRef!=null?"StrongRef not gc":"StrongRef is gc");
    }
    }

    -------------------------------------------------------------------------------------------------------------------------------

    2,软引用;

    package com.myjava.reference;
    import java.lang.ref.SoftReference;
    /**
     * ①,softReference 软引用在内存充足时不会被GC,
     * ②,当内存空间不足时就会回收这些对象的内存
     * ③,适合做高速访问,如cache--Android开发中
     * @author Administrator
     *
     */
    public class TestSoftReference {
    public static void main(String[] args) {
    String str = "test soft GC";
    SoftReference<String> softReference = new SoftReference<String>(str);
    str = null;
    System.gc();
    System.out.println(softReference.get() != null ? "softReference not gc"
    : "softReference is gc");
    }
    }

    ----------------------------------------------------------------------------------------------------------

    弱引用:

    package com.myjava.reference;
    import java.lang.ref.WeakReference;
    /**
     * ①,不管当前内存空间足够与否,都会回收它的内存。
     * ②,结合ReferenceQueue可以让程序在第一时间得到referent被回收的事件
     * ③,一般用来防止内存泄漏,要保证内存被VM回收
     * @author Administrator
     *
     */
    public class TestWeakReference {
    public static void main(String[] args) {
    String   str  =   "test weakReference " ;  
    WeakReference < String >   weakReference  =  new  WeakReference <String>(str);  
    str = null;  
    System.gc();  
    System.out.println(weakReference.get()!= null? "weakReference not gc": "weakReference is gc");  
    }
    }

    http://blog.csdn.net/xhh198781/article/details/6459926

    http://zhangjunhd.blog.51cto.com/113473/53092/

    http://blog.csdn.net/rzhzhz/article/details/7679032

    -----------------------------------------------------------------------------------------------------------------

    4,虚引用

    package com.myjava.reference;


    import java.lang.ref.PhantomReference;
    import java.lang.ref.Reference;
    import java.lang.ref.ReferenceQueue;
    import java.util.HashMap;
     
    public class TestPhantomReference {
     
        public static void main(String[] args) {
            ReferenceQueue referenceQueue = new ReferenceQueue();
            Object object = new Object() {
                public String toString() {
                    return "Referenced Object";
                }
            };
     
            Object data = new Object() {
                public String toString() {
                    return "Data";
                }
            };
     
            HashMap map = new HashMap();
            Reference reference = null;
            System.out.println("Testing PhantomReference.");
            reference = new PhantomReference(object, referenceQueue);
     
            map.put(reference, data);
     
            System.out.println(reference.get()); // null
            System.out.println(map.get(reference)); // Data
            System.out.println(reference.isEnqueued()); // false
     
            System.gc();
            System.out.println(reference.get()); // null
            System.out.println(map.get(reference)); // Data
            System.out.println(reference.isEnqueued()); // false
     
            object = null;
            data = null;
     
            System.gc();
            System.out.println(reference.get()); // null
            System.out.println(map.get(reference)); // Data
            System.out.println(reference.isEnqueued()); // true, because object has been reclaimed.
        }
     
    }

    http://www.oschina.net/question/12_8662

    Strong Reference, 强引用,即java标准的引用方式,表示GC从 Root Set 开始向下扫描,可以找到对应的 Strong Reference。

    Referent,被包装为 Weak, Soft, Phantom Reference的对象引用称之为 referent。后面的内容会多次提到这个名词。

    Weak Reference, 弱引用。当一个referent,在运行时没有同时被强,软引用,只被Weak Reference自身引用,且Weak Reference从 Root Set 可达,则该referent会被GC回收。

    WR的作用,一般是为referent提供一个被回收的凭据,结合ReferenceQueue可以让程序在第一时间得到referent被回收的事件,从而做一些额外的clean操作。(如果对ReferenceQueue作用和回调感兴趣,可以先看最下面的 ReferenceQueue 简介)

    Soft Reference, 软引用。它是除strong外,生命周期最长的一种 Reference,只有当JVM Heap中充满Strong References, Full GC无法为heap腾出更多空间而即将抛出OOM时,SoftReferences会被GC回收。

    SR的作用一般是用作不限大小的 cache(无需remove)。
    比如将其 Soft Reference 无限地放入 hashmap 中,而不关心hashmap内的对象数量是否会撑爆heap,也不需要手动 remove。
    当Heap容量达到OOM触发条件时,VM会自动回收该map里的所有SoftReferences.

    Phanton Reference, 是一种特殊的Reference,正如他的名字所表达的,幻影引用,他可以像幻影一样附着在referent上。
    当GC在遍历引用关系时,如果发现被phantom reference包装过的referent不存在strong, weak, soft引用时(就是除phantom外没有任何引用,幻影的由来),GC会将 phantom reference 放入 Reference queue。以便程序在另一边通过queue的remove/poll方法,感知referent被GC回收的事件。(如果对 ReferenceQueue作用和回调感兴趣,可以先看最下面 ReferenceQueue 简介)

    另外,我们知道,GC在回收对象前会先调用对象自身的finalize()方法,如果它有实现的话,然后再清掉内存。而Phantom Reference的回调(enqueue)是在对象的finalize后,回收前触发。这跟 WeakReference不一样。WR是在回收后才通知的。在这个特殊的阶段可以做一些特殊的clean操作。

    为什么 Phantom Reference 的get总是返回null?
    因为phantom reference想做到幻影(除自身外,不跟其他任何引用有关联),所以不允许程序能通过自身的get方法得到referent,而破坏幻影的初衷。

    实例代码

    package com.kenwublog.reference;
     
    import java.lang.ref.PhantomReference;
    import java.lang.ref.Reference;
    import java.lang.ref.ReferenceQueue;
    import java.util.HashMap;
     
    public class PhantomReferenceTest {
     
        public static void main(String[] args) {
            ReferenceQueue referenceQueue = new ReferenceQueue();
            Object object = new Object() {
                public String toString() {
                    return "Referenced Object";
                }
            };
     
            Object data = new Object() {
                public String toString() {
                    return "Data";
                }
            };
     
            HashMap map = new HashMap();
            Reference reference = null;
            System.out.println("Testing PhantomReference.");
            reference = new PhantomReference(object, referenceQueue);
     
            map.put(reference, data);
     
            System.out.println(reference.get()); // null
            System.out.println(map.get(reference)); // Data
            System.out.println(reference.isEnqueued()); // false
     
            System.gc();
            System.out.println(reference.get()); // null
            System.out.println(map.get(reference)); // Data
            System.out.println(reference.isEnqueued()); // false
     
            object = null;
            data = null;
     
            System.gc();
            System.out.println(reference.get()); // null
            System.out.println(map.get(reference)); // Data
            System.out.println(reference.isEnqueued()); // true, because object has been reclaimed.
        }
     
    }


    ReferenceQueue,一种当 weak, soft, phantom的referent被GC回收后,提供事件回调的接口。需要在实例化三大reference时,通过构造函数传入,phantom reference是强制需要传入的,weak和soft可不传。

    回调过程:

    GC回收referent后(phantom是在回收前,finalize后),将reference enqueue到RQ中,程序通过调用RQ的remove方法来感知reference被GC回收的事件。
    remove方法是阻塞的,当没有referent被回收时(GC未调用enqueue),remove方法会一直挂起线程,当有referent被回收时,该方法返回 referent对应的reference对象。
    同样,RQ也提供了一个非阻塞的方法 poll,但这样就做不到实时回调了。

    实例

    package com.kenwublog.reference;
     
    import java.lang.ref.Reference;
    import java.lang.ref.ReferenceQueue;
    import java.lang.ref.WeakReference;
    import java.util.HashMap;
     
    public class ReferenceQueueTest {
     
        public static void main(String[] args) {
            final ReferenceQueue q = new ReferenceQueue();
            String str = new String("AK47");
            WeakReference wr = new WeakReference(str, q);
     
            Thread t = new Thread(){
                @Override
                public void run() {
                    try {
                        Reference reference = q.remove();
                        System.out.println(reference + " event fired.");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            t.setDaemon(true);
            t.start();
            System.out.println("Reference Queue is listening.");
     
            str = null; // clear strong reference
            System.out.println("Ready to gc");
            System.gc();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wr.get: " + wr.get());
        }
     
    }


  • 相关阅读:
    阿诺尔德给5至15岁孩子出的数学题
    上手机器学习,从搞懂这十大经典算法开始
    海报模板
    测度论--长度是怎样炼成的[zz]
    柯西不是你
    搭建Web部署环境
    搭建jdk环境
    Win10远程桌面 出现 身份验证错误,要求的函数不受支持,这可能是由于CredSSP加密Oracle修正 解决方法
    Web开发技术选型之Java与PHP
    从java到web前端再到php,一路走来的小总结
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3000932.html
Copyright © 2011-2022 走看看