1.強引用
強引用就是我們平時使用最多的那種引用,就比如以下的代碼
//創建一個對象
Object obj = new Object();//強引用
這個例子就是創建了一個對象并建立了強引用,強引用一般就是默認支持的當內存不足的時候,JVM開始垃圾回收,對于強引用的對象,就算是出現了OOM也不會回收對象。即使在解除對對象的強引用后,只要系統內存充足,垃圾回收器不會立即回收對象。強引用使得對象在被引用時一直保持有效,直到引用被顯式解除。
以下三種引用就是比較不常見的了,這三種引用雖然叫引用但是和我們理解的那種棧上的變量指向堆上的對象的指針不是一回事。
千萬不要將軟弱虛這三種引用理解為那種棧上的變量指向堆上的對象的指針。
軟引用、弱引用、虛引用:這三種引用其實就是一個個的類,通過對應的類名翻譯過來的中文名稱。
// 軟引用
public class SoftReference<T> extends Reference<T> {}// 弱引用
public class WeakReference<T> extends Reference<T> {}// 虛引用
public class PhantomReference<T> extends Reference<T> {}
?
2.軟引用
發生了垃圾回收,并且回收后內存仍然不足,并且被軟引用指向的對象沒有強引用,那么被軟引用指向的對象就會被回收。
public class SoftReferenceDemo {public static void main(String[] args) {Object a = new Object();SoftReference softReference = new SoftReference<>(a);//軟引用//a和軟引用指向同一個對象System.out.println(a);//java.lang.Object@4554617cSystem.out.println(softReference.get());//java.lang.Object@4554617c//內存夠用,軟引用不會被回收a = null;System.gc();//內存夠用不會自動gc,手動喚醒gcSystem.out.println(a);//nullSystem.out.println(softReference.get());//java.lang.Object@4554617c//內存不夠用時try{//配置Xms和Xmx為5MBbyte[] bytes = new byte[1024102430];//設置30MB超內存}catch (Throwable e){e.printStackTrace();}finally {System.out.println(a);//nullSystem.out.println(softReference.get());//null}}
}
第一步
第二步撤了對a對象的強引用只剩軟引用了,手動喚醒gc對象被清除了
3.弱引用
弱引用(Weak Reference)是Java中一種比強引用更弱的引用類型。當一個對象只被弱引用關聯時,在下一次垃圾回收時,該對象就有可能被回收。垃圾回收器會在適當的時候回收僅被弱引用持有的對象,即使內存并不緊張。
public class WeakReferenceDemo {public static void main(String[] args) {// 創建一個對象并建立弱引用Object obj = new Object();WeakReference<Object> weakRef = new WeakReference<>(obj);// 對象仍然存在,可以正常使用System.out.println("Object is still accessible: " + weakRef.get());// 解除對對象的強引用obj = null;// 手動觸發垃圾回收System.gc();// 垃圾回收后,對象被回收,弱引用返回nullSystem.out.println("Object after garbage collection: " + weakRef.get());}}
- 軟引用和弱引用一般都可以被用于實現內存敏感的緩存
- ThreadLocalMap中的entry實體就是一個弱引用
static class ThreadLocalMap {// Entry是一個弱引用static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}
}
為什么要在ThreadLocal中使用弱引用?
先簡單說一下在?ThreadLocal?的實現中,它使用了一個名為?ThreadLocalMap?的哈希表來存儲每個線程的局部變量。這個?ThreadLocalMap?的鍵(Key)是?ThreadLocal?對象的弱引用,而值(Value)則是與線程相關聯的實際對象。
1.防止內存泄露:使用弱引用允許 JVM 在內存緊張時回收?ThreadLocal?對象,而不必等待整個ThreadLocalMap?被顯式清理。這種靈活性有助于更好地管理內存,特別是在高負載或長時間運行的應用程序中。
2.靈活的內存管理:使用弱引用允許 JVM 在內存緊張時回收?ThreadLocal?對象,而不必等待整個?ThreadLocalMap?被顯式清理。這種靈活性有助于更好地管理內存,特別是在高負載或長時間運行的應用程序中。
4.虛引用
虛引用(Phantom Reference)是Java中最弱的引用類型之一,無法通過引用直接獲取到對象實例。虛引用主要用于跟蹤對象被垃圾回收的狀態。當一個對象只被虛引用關聯時,其實際上并不影響對象的生命周期,也就是說,垃圾回收器隨時可能回收被虛引用關聯的對象,我們甚至無法通過get方法獲取到對象實例。