Java中的四大引用筆記

李納斯小盒發表於2018-05-21

Android 開發筆記 onGithub

[TOC]

按引用強度遞減的順序

  • 1.強引用
  • 2.軟引用
  • 3.弱引用
  • 4.虛引用

1.強引用(Strong Reference)

Object o = new Object()

只要強引用還存在,垃圾收集器永遠不會回收掉被引用的物件

2.軟引用(Soft Reference)

描述一些還有用但並非必須的物件

對於軟引用關聯著的物件,在系統將要發生記憶體溢位異常之前,將會把這些物件列進回收範圍之中進行第二次回收。如果這次回收還沒有足夠的記憶體,才會丟擲記憶體溢位異常。在JDK1.2之後,提供了SoftReference類來實現軟引用。

3.弱引用(Weak Reference)

弱引用也是用來描述非必需物件的,但是它的強度比軟引用更弱一些,被弱引用關聯的物件只能生存到下一次垃圾收集發生之前。當垃圾收集器工作時,無論當前記憶體是否足夠,都會回收掉只被弱引用關聯的物件。在JDK1.2之後,提供了WeakReference類來實現弱引用。

4.虛引用(Phantom Reference)

虛引用也稱為幽靈引用或者幻影引用,它是最弱的一種引用關係。一個物件是否有虛引用的存在,完全不會對其生存時間構成影響,也無法通過虛引用來取得一個物件例項。為一個物件設定虛引用關聯的唯一目的就是能在這個物件被收集器回收時收到一個系統通知。

關於虛引用得到回收的通知:參考

package static_;
 
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;
 
public class Test {
    public static boolean isRun = true;
 
    @SuppressWarnings("static-access")
    public static void main(String[] args) throws Exception {
        String abc = new String("abc");
        System.out.println(abc.getClass() + "@" + abc.hashCode());
        final ReferenceQueue<String> referenceQueue = new ReferenceQueue<String>();
        new Thread() {
            public void run() {
                while (isRun) {
                    Object obj = referenceQueue.poll();
                    if (obj != null) {
                        try {
                            Field rereferent = Reference.class
                                    .getDeclaredField("referent");
                            rereferent.setAccessible(true);
                            Object result = rereferent.get(obj);
                            System.out.println("gc will collect:"
                                    + result.getClass() + "@"
                                    + result.hashCode() + "\t"
                                    + (String) result);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }.start();
        PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc,
                referenceQueue);
        abc = null;
        Thread.currentThread().sleep(3000);
        System.gc();
        Thread.currentThread().sleep(3000);
        isRun = false;
    }
}
複製程式碼

我們用一個執行緒檢測referenceQueue裡面是不是有內容,如果有內容,列印出來queue裡面的內容。

從這個例子中,我們可以看出來,虛引用的作用是,我們可以宣告虛引用來引用我們感興趣的物件,在gc要回收的時候,gc收集器會把這個物件新增到referenceQueue,這樣我們如果檢測到referenceQueue中有我們感興趣的物件的時候,說明gc將要回收這個物件了。此時我們可以在gc回收之前做一些其他事情,比如記錄些日誌什麼的。

相關文章