zoukankan      html  css  js  c++  java
  • Java基础

    1、强引用(StrongReference)
       

          强引用是使用最普遍的引用。

    假设一个对象具有强引用。那垃圾回收器绝不会回收它。例如以下:

    1. Object o = new Object();   //  强引用  
          当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误。使程序异常终止,也不会靠任意回收具有强引用的对象来解决内存不足的问题。假设不使用时,要通过例如以下方式来弱化引用,例如以下:
    1. o = null;     // 帮助垃圾收集器回收此对象  
          显式地设置o为null,或超出对象的生命周期范围,则gc觉得该对象不存在引用,这时就能够回收这个对象。详细什么时候收集这要取决于gc的算法。


    举例:

    1. public void test(){  
    2.     Object o = new Object();  
    3.     // 省略其它操作  
    4. }  
    在一个方法的内部有一个强引用。这个引用保存在栈中,而真正的引用内容(Object)保存在堆中。当这种方法执行完毕后就会退出方法栈。则引用内容的引用不存在。这个Object会被回收。

    可是假设这个o是全局的变量时,就须要在不用这个对象时赋值为null。由于强引用不会被垃圾回收。

    强引用在实际中有很重要的用处,举个ArrayList的实现源码:

    1. private transient Object[] elementData;  
    2. public void clear() {  
    3.         modCount++;  
    4.         // Let gc do its work  
    5.         for (int i = 0; i < size; i++)  
    6.             elementData[i] = null;  
    7.         size = 0;  
    8. }  
    在ArrayList类中定义了一个私有的变量elementData数组,在调用方法清空数组时能够看到为每一个数组内容赋值为null。

    不同于elementData=null,强引用仍然存在。避免在兴许调用 add()等方法加入元素时进行又一次的内存分配。使用如clear()方法中释放内存的方法对数组中存放的引用类型特别适用,这样就能够及时释放内存。



    2、软引用(SoftReference)

        

            假设一个对象仅仅具有软引用。则内存空间足够,垃圾回收器就不会回收它;假设内存空间不足了,就会回收这些对象的内存

    仅仅要垃圾回收器没有回收它。该对象就能够被程序使用。软引用可用来实现内存敏感的快速缓存。   

    1. String str = new String("abc");                                     // 强引用  
    2. SoftReference<String> softRef = new SoftReference<String>(str);     // 软引用    
          当内存不足时。等价于:

    1. If(JVM.内存不足()) {  
    2.    str = null;  // 转换为软引用  
    3.    System.gc(); // 垃圾回收器进行回收  
    4. }  

    虚引用在实际中有重要的应用,比如浏览器的后退button。按后退时,这个后退时显示的网页内容是又一次进行请求还是从缓存中取出呢?这就要看详细的实现策略了。

    (1)假设一个网页在浏览结束时就进行内容的回收。则按后退查看前面浏览过的页面时,须要又一次构建

    (2)假设将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出

    这时候就能够使用软引用

    1. Browser prev = new Browser();               // 获取页面进行浏览  
    2. SoftReference sr = new SoftReference(prev); // 浏览完成后置为软引用         
    3. if(sr.get() != null){   
    4.     rev = (Browser) sr.get();           // 还没有被回收器回收,直接获取  
    5. }else{  
    6.     prev = new Browser();               // 因为内存吃紧,所以对软引用的对象回收了  
    7.     sr = new SoftReference(prev);       // 又一次构建  
    8. }  
    这样就非常好的攻克了实际的问题。


           软引用能够和一个引用队列(ReferenceQueue)联合使用,假设软引用所引用的对象被垃圾回收器回收。Java虚拟机就会把这个软引用增加到与之关联的引用队列中。


    3、弱引用(WeakReference)

        

          弱引用与软引用的差别在于:仅仅具有弱引用的对象拥有更短暂的生命周期。

    在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了仅仅具有弱引用的对象,无论当前内存空间足够与否,都会回收它的内存。只是。因为垃圾回收器是一个优先级非常低的线程。因此不一定会非常快发现那些仅仅具有弱引用的对象。

    1. String str = new String("abc");      
    2. WeakReference<String> abcWeakRef = new WeakReference<String>(str);  
    3. str=null;    

    当垃圾回收器进行扫描回收时等价于:

    1. str = null;  
    2. System.gc();  

       假设这个对象是偶尔的使用。而且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么你应该用 Weak Reference 来记住此对象。   

       以下的代码会让str再次变为一个强引用:

    1. String  abc = abcWeakRef.get();  

    弱引用能够和一个引用队列(ReferenceQueue)联合使用,假设弱引用所引用的对象被垃圾回收。Java虚拟机就会把这个弱引用增加到与之关联的引用队列中。

    当你想引用一个对象。可是这个对象有自己的生命周期。你不想介入这个对象的生命周期。这时候你就是用弱引用。

    这个引用不会在对象的垃圾回收推断中产生不论什么附加的影响。

    1. public class ReferenceTest {  
    2.   
    3.     private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>();  
    4.   
    5.     public static void checkQueue() {  
    6.         Reference<? extends VeryBig> ref = null;  
    7.         while ((ref = rq.poll()) != null) {  
    8.             if (ref != null) {  
    9.                 System.out.println("In queue: " + ((VeryBigWeakReference) (ref)).id);  
    10.             }  
    11.         }  
    12.     }  
    13.   
    14.     public static void main(String args[]) {  
    15.         int size = 3;  
    16.         LinkedList<WeakReference<VeryBig>> weakList = new LinkedList<WeakReference<VeryBig>>();  
    17.         for (int i = 0; i < size; i++) {  
    18.             weakList.add(new VeryBigWeakReference(new VeryBig("Weak " + i), rq));  
    19.             System.out.println("Just created weak: " + weakList.getLast());  
    20.   
    21.         }  
    22.   
    23.         System.gc();   
    24.         try { // 以下歇息几分钟。让上面的垃圾回收线程执行完毕  
    25.             Thread.currentThread().sleep(6000);  
    26.         } catch (InterruptedException e) {  
    27.             e.printStackTrace();  
    28.         }  
    29.         checkQueue();  
    30.     }  
    31. }  
    32.   
    33. class VeryBig {  
    34.     public String id;  
    35.     // 占用空间,让线程进行回收  
    36.     byte[] b = new byte[2 * 1024];  
    37.   
    38.     public VeryBig(String id) {  
    39.         this.id = id;  
    40.     }  
    41.   
    42.     protected void finalize() {  
    43.         System.out.println("Finalizing VeryBig " + id);  
    44.     }  
    45. }  
    46.   
    47. class VeryBigWeakReference extends WeakReference<VeryBig> {  
    48.     public String id;  
    49.   
    50.     public VeryBigWeakReference(VeryBig big, ReferenceQueue<VeryBig> rq) {  
    51.         super(big, rq);  
    52.         this.id = big.id;  
    53.     }  
    54.   
    55.     protected void finalize() {  
    56.         System.out.println("Finalizing VeryBigWeakReference " + id);  
    57.     }  
    58. }  

    最后的输出结果为:

    1. Just created weak: com.javabase.reference.VeryBigWeakReference@1641c0  
    2. Just created weak: com.javabase.reference.VeryBigWeakReference@136ab79  
    3. Just created weak: com.javabase.reference.VeryBigWeakReference@33c1aa  
    4. Finalizing VeryBig Weak 2  
    5. Finalizing VeryBig Weak 1  
    6. Finalizing VeryBig Weak 0  
    7. In queue: Weak 1  
    8. In queue: Weak 2  
    9. In queue: Weak 0  



    4、虚引用(PhantomReference)

       

         “虚引用”顾名思义,就是形同虚设。与其它几种引用都不同。虚引用并不会决定对象的生命周期。

    假设一个对象仅持有虚引用。那么它就和没有不论什么引用一样,在不论什么时候都可能被垃圾回收器回收。

        虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个差别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,假设发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用增加到与之 关联的引用队列中。



    5、总结

     Java4种引用的级别由高到低依次为:

    强引用  >  软引用  >  弱引用  >  虚引用

    通过图来看一下他们之间在垃圾回收时的差别:


    当垃圾回收器回收时,某些对象会被回收,某些不会被回收。

    垃圾回收器会从根对象Object来标记存活的对象。然后将某些不可达的对象和一些引用的对象进行回收,假设对这方面不是非常了解,能够參考例如以下的文章:

    传送门:Java内存管理  http://blog.csdn.net/mazhimazh/article/category/1907599

    通过表格来说明一下。例如以下:

    引用类型

    被垃圾回收时间

       用途

       生存时间

    强引用

    从来不会

    对象的一般状态

    JVM停止执行时终止

    软引用

    在内存不足时

    对象缓存

    内存不足时终止

    弱引用

    在垃圾回收时

    对象缓存

    gc执行后终止

    虚引用

    Unknown

    Unknown

    Unknown



  • 相关阅读:
    JavaScript cookie详解
    Javascript数组的排序:sort()方法和reverse()方法
    javascript中write( ) 和 writeln( )的区别
    div做表格
    JS 盒模型 scrollLeft, scrollWidth, clientWidth, offsetWidth 详解
    Job for phpfpm.service failed because the control process exited with error code. See "systemctl status phpfpm.service" and "journalctl xe" for details.
    orm查询存在价格为空问题
    利用救援模式破解系统密码
    SSH服务拒绝了密码
    C# 调用 C++ DLL 中的委托,引发“对XXX::Invoke类型的已垃圾回收委托进行了回调”错误的解决办法
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/6849140.html
Copyright © 2011-2022 走看看