上章說標記算法經過根標記可達對象。是否可達(可觸)這與實例的引用級別也有很大的關係。下面說幾種在java中的引用級別,除了強引用其餘3種均可以在java.lang.ref中找到 java
1.強引用 算法
程序中默認的引用方式。正常的賦值就是如 List<String> strs = new ArrayList()<String>() ; 那麼 strs就是一個強引用。被強引用的對象爲可達(可觸)對象,GC沒法對其回收就算內存溢出也不肯意 緩存
2.軟引用 ide
被軟引用的對象在GC以爲內存不足時就會對其進行回收,沒法知道對象在哪一時刻被銷燬。這種引用用於緩存最好不過了。例: this
import java.lang.ref.SoftReference; public class SoftRef { public static class People{ private String name; private String gender; public People(String name, String gender) { this.name = name; this.gender = gender; } //get/set .... } public static void main(String[] args) { People zs = new People("張三", "男");//這是一個強引用 SoftReference<People> PeopleSoftRef = new SoftReference<SoftRef.People>(zs);//建立了軟引用 zs = null; //消除強引用 zs = PeopleSoftRef.get(); //軟引用方式取得對象,這個對象有可能不存在被GC回收了 } }
3.弱引用 spa
比軟件引用更加弱了,被弱引用的對象在GC一觸發時就被銷燬了。一樣合適與緩存方式(但沒有上面好,由於GC觸發機率是比較高的,因此數據很容易被銷燬)例: code
import java.lang.ref.WeakReference; public class WeakSoft { public static class People{ //somethig... } public static void main(String[] args) { WeakReference<People> peopleWeak = new WeakReference<WeakSoft.People>(new People("張三", "男")); People zs = peopleWeak.get(); //弱引用方式取得對象,這個對象頗有可能已經被銷燬了 } }
4.虛引用(瞭解) 對象
這個是引用類型中最弱的,持有虛引用的對象有跟沒有同樣。如上當你試圖用get()取出,總會失敗。是一個不可達對象,虛引用必須和引用隊列一塊兒使用。它的做用僅僅在於跟蹤回收過程(就是它被GC回收,在隊列中讓你知道一下就ok了)。 隊列
-------------------------------------------------------------------- 進程
擴展 軟引用、弱引用、虛引用與它們的引用隊列
這三種引用隨時會被GC回收,但回收後它會被丟到引用隊列中,在隊列中你能夠找到它們的身影,但僅用來跟蹤查看而已例:
java -Xmx10M -XX:+PrintGC WeakSoft
import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; public class WeakSoft { public static ReferenceQueue<People> peopleWeakQueue = new ReferenceQueue<People>();//引用隊列 public static class People{ //somethig } public static class PeopleWeakRef extends WeakReference<People>{ private String name; public PeopleWeakRef(People referent, ReferenceQueue<? super People> q) { super(referent, q); this.name = referent.getName(); } //get/set } public static class TraceRefQueue implements Runnable{ @Override public void run() { while (true) { PeopleWeakRef peopleRef = null; try { peopleRef = (PeopleWeakRef) peopleWeakQueue.remove(); } catch (InterruptedException e) { throw new RuntimeException(e); } if(peopleRef!=null){ System.out.println(peopleRef.getName()+" 被移除了!"); System.out.println(peopleRef.get()); } } } } public static void main(String[] args) throws InterruptedException { Thread traceRefQueueThread = new Thread(new TraceRefQueue());//啓動一個守護進程,監聽GC移除動做 traceRefQueueThread.setDaemon(true); traceRefQueueThread.start(); PeopleWeakRef peopleWeakRef = new PeopleWeakRef(new People("張三", "男"),peopleWeakQueue); //讓GC觸發 byte[] memory = new byte[3*1024*1024]; memory = new byte[2*1024*1024]; memory = new byte[2*1024*1024]; } }最後結果:
[GC 5794K->5632K(9728K), 0.0078318 secs]
張三 被移除了!
null
輸出說明:看到GC觸發了一次,這時「張三」對象就被銷燬了。在引用隊列中能夠獲取了它的弱引用,但你再也找不回「張三」了。