內存泄漏為程序在申請內存后,無法釋放已申請的內存空間,一次泄露危害可以忽略,但內存泄漏堆積后果很嚴重,無論多少內存,遲早會被占光。
不再會被使用的對象或者變量占用的內存空間不能被回收,就是內存泄漏。
強引用:使用最普遍的一個引用(new),一個對象具有強引用,不會被垃圾收集器回收。當內存空間不足,java虛擬機寧願OOM,都不會回收。
如果想取消強引用和某個對象之間的關聯,可以顯示將對象復制為null,這樣jvm就會在安全區域執行gc進行垃圾回收。
弱引用:jvm進行垃圾回收時,無論內存是否充足,都會回收被弱引用關聯的對象。在java中,用WeakReference類來表示。
ThreadLocal的實現原理,每一個Thread維護一個ThreadLocalMap,ThreadLocalMap是由一個個Entry構成,而Entry繼承了弱引用,key為使用弱引用的ThreadLocal對象,value為線程變量的副本。
ThreadLocalMap使用ThreadLocal的弱引用作為key,如果一個ThreadLocal不存在外部的強引用時,Key(ThreadLocal對象)勢必會被GC回收,這樣就會導致ThreadLocalMap中的key為null,而value還存在着強引用,只有thread線程退出以后,value的強引用鏈才會斷掉,但是如果線程遲遲不結速的話,這些key為null的Entry的value就會一直存在引用鏈。
key使用強引用
當ThreadLocalMap的key使用強引用時,此時若是外部的ThreadLocal對象被置為null,按理說應該被回收,但是ThreadLocalMap中還持有對ThreadLocal的強引用,如果沒有手動刪除,那么ThreadLocal不會被回收,導致Entry內存泄漏。
key使用弱引用
當ThreadLocalMap的key為弱引用回收ThreadLocal對象時,由於ThreadLocalMap只持有ThreadLocal的弱引用,即使沒有手動刪除,也不會影響ThreadLocal的回收。當key為null時,在下一個調用ThreadLocalMap的set、get、remove方法時會清除value值。
ThreadLocal正確使用方法
- 每次使用完ThreadLocal都調用它的remove方法清楚數據
- 將ThreadLocal變量定義為private static,這樣就一直存在ThreadLocal的強引用,也就能保證在任何時候都能通過ThreadLocal的弱引用訪問到Entry的value值,繼續清除。