四種引用類型
強引用:
強引用又稱‘普通引用’,如:T t = new T();
這種引用類型永遠都不會被回收。
軟引用:
SoftReference<T> m = new SoftReference<>(new T());
此種引用只有在內存不足的情況下回收,一般用於緩存對象、圖片等對象,用完一次就不用的場景。
弱引用:
WeakReference<T> m = new WeakReference<>(new T());
弱引用在調用 System.gc();時就會回收。
一般用在容器裏,如ThreadLocal:
ThreadLocal 往裏set值的時候,是往當前線程的Map 中放數據,key就是ThreadLocal對象,value是具體對象,在往map中set(確實是set)的時候,其實是一個Entry對象,這個Entry對象就繼承了WeakReference類,是一個弱引用,噹噹前線程結束的時候,此時的key也就是ThreadLocal對象就會自動被回收。
如果這個key不是弱引用,而是強引用,在當前線程結束的時候,這個key,也就是ThreadLocal對象是不會被回收的。會導致內存泄露。
所以,使用ThreadLocal,不用以後,必須把對象remove掉。
WeakHashMap???
虛引用:
虛引用主要用於堆外內存的。
PhantomReference<T> m = new PhantomReference<>(new T(),QUEUE);
這個東西是給寫虛擬機(JVM)的人用的,程序員一般用不上。
垃圾回收只要看到有虛引用,二話不說,直接回收。當對象被回收的時候,會通知你,將對象的引用放入QUEUE 中,也就是說,只要隊列中有引用,說明這個對象已被回收。
還有一點,虛引用裏邊的值是get不到的。
NIO中有個DirectByteBuffer就是堆外內存(直接內存),使用的虛引用,它不歸JVM管理,而是操作系統,什麼時候去回收這塊堆外內存呢?可以去監聽這個隊列,當這個隊列中有值時,就去清理堆外內存。
怎麼回收堆外內存?
通過Unsafe,還有直接分配內存、釋放內存的api
內存泄露和內存溢出的區別:
內存泄露可以理解爲 漏掉了一塊,永遠不會被回收;內存溢出是指佔用的內存越來越多,佔不下了導致溢出。