在Java中,引用分為強引用、軟引用、弱引用和虛引用四種。
- 強引用,程式碼中普遍存在的形式,例如常見的普通類new出物件後的引用。GC不會回收強引用的物件。
- 軟引用,軟引用物件會在記憶體溢位異常之前進行回收,也就是說在記憶體富裕的情況下GC不回收軟引用。它可通過SoftReference類實現。
- 弱引用,弱引用物件會在下一次GC時被回收,也就是說不管記憶體富不富裕,當GC時都會回收弱引用。它可通過WeakReference類實現。
- 虛引用,虛引用不會改變物件的生存時間,它只是讓物件在被GC時能收到一個系統通知。
瞭解了所有引用型別後看下如何基於弱引用對程式進行記憶體洩漏檢測。
假如在你的程式中有某類的物件很可能會造成記憶體洩漏,姑且稱為MaybeMemoryLeak類。記憶體洩漏就是虛擬機器在做垃圾回收時某些“垃圾”由於某些原因而導致無法回收,每次例項化出來的物件都無法回收,最終導致記憶體爆了。也就是如果某些MaybeMemoryLeak應該被回收的物件無法回收,就會導致記憶體洩漏。
如果無法避免記憶體洩漏的可能性,那麼如何檢測記憶體洩漏現象呢?
這裡就要用到上面所說的弱引用,它能很好判斷MaybeMemoryLeak有沒有被GC回收,被弱引用關聯的物件只能生存到下一次垃圾回收發生之前,即如果某MaybeMemoryLeak物件只被某弱引用關聯,則它會在下次垃圾回收時被回收,但如果MaybeMemoryLeak物件除了被弱引用關聯外還被其他物件強引用,那麼MaybeMemoryLeak物件是不會被回收的,根據這些條件就可以判斷是否有MaybeMemoryLeak記憶體洩漏了。
在實際的實現中可以通過WeakHashMap來實現弱引用,只需將MaybeMemoryLeak物件put到WeakHashMap中,例如weakMap.put(“a”,maybeMemoryLeak),當maybeMemoryLeak及其包含的元素沒有被其它任何類載入器中的元素引用到時,JVM發生垃圾回收時則會把maybeMemoryLeak物件回收,否則就將一直回收不了。
這裡使用一個WeakHashMap用於追蹤MaybeMemoryLeak物件,在查詢記憶體洩漏之前要先強制呼叫System.gc();進行一次垃圾回收,保證沒問題的MaybeMemoryLeak物件都被回收掉,這時可以檢視WeakHashMap物件還存在哪些MaybeMemoryLeak物件,如果存在某些“垃圾”MaybeMemoryLeak物件,則屬於記憶體洩漏。
====廣告時間,可直接跳過====
鄙人的新書《Tomcat核心設計剖析》已經在京東預售了,有需要的朋友可以到 item.jd.com/12185360.ht… 進行預定。感謝各位朋友。
=========================
歡迎關注: