https://github.com/Androooid/treasure/blob/master/source/lightsky/posts/mat_usage.md
1.1 GC Root
JAVA虛擬機通過可達性(Reachability)來判斷對象是否存活,基本思想:以"GC Roots"的對象作為起始點向下搜索,搜索形成的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈相連(即不可達的),則該對象被判定為可以被回收的對象,反之不能被回收。
GC Roots可以是以下任意對象
- 一個在current thread(當前線程)的call stack(調用棧)上的對象(例如方法參數和局部變量)
- 線程自身或者system class loader(系統類加載器)加載的類
- native code(本地代碼)保留的活動對象
1.2 內存泄漏
對象無用了,但仍然可達(未釋放),垃圾回收器無法回收。
1.3 強(strong)、軟(soft)、弱(weak)、虛(phantom)引用
Strong references
普通的java引用,我們通常new的對象就是: StringBuffer buffer = new StringBuffer(); 如果一個對象通過一串強引用鏈可達,那么它就不會被垃圾回收。你肯定不希望自己正在使用的引用被垃圾回收器回收吧。但對於集合中的對象,應在不使用的時候移除掉,否則會占用更多的內存,導致內存泄漏。
Soft reference
當對象是Soft reference可達時,gc會向系統申請更多內存,而不是直接回收它,當內存不足的時候才回收它。因此Soft reference適合用於構建一些緩存系統,比如圖片緩存。
WeakReference
WeakReference不會強制對象保存在內存中。它擁有比較短暫的生命周期,允許你使用垃圾回收器的能力去權衡一個對象的可達性。在垃圾回收器掃描它所管轄的內存區域過程中,一旦gc發現對象是weakReference可達,就會把它放到ReferenceQueue中,等下次gc時回收它。 WeakReference<Widget> weakWidget = new WeakReference<Widget>(widget); 系統為我們提供了WeakHashMap,和HashMap類似,只是其key使用了weak reference。如果WeakHashMap的某個key被垃圾回收器回收,那么entity也會自動被remove。
由於WeakReference被GC回收的可能性較大,因此,在使用它之前,你需要通過weakObj.get()去判斷目的對象引用是否已經被回收.
Reference queque
一旦WeakReference.get()返回null,它指向的對象就會被垃圾回收,那么WeakReference對象就沒有用了,意味着你應該進行一些清理。比如在WeakHashMap中要把回收過的key從Map中刪除掉,避免無用的的weakReference不斷增長。 ReferenceQueue可以讓你很容易地跟蹤dead references。WeakReference類的構造函數有一個ReferenceQueue參數,當指向的對象被垃圾回收時,會把WeakReference對象放到ReferenceQueue中。這樣,遍歷ReferenceQueue可以得到所有回收過的WeakReference。
Phantom reference
和soft,weak Reference區別較大,它的get()方法總是返回null。這意味着你只能用PhantomReference本身,而得不到它指向的對象。當WeakReference指向的對象變得弱可達(weakly reachable)時會立即被放到ReferenceQueue中,這在finalization、garbage collection之前發生。理論上,你可以在finalize()方法中使對象“復活”(使一個強引用指向它就行了,gc不會回收它)。但沒法復活PhantomReference指向的對象。而PhantomReference是在garbage collection之后被放到ReferenceQueue中的,沒法復活。
關於Phantom reference的更多討論,請參考:understanding-weak-references
