Java引用機(jī)制之強(qiáng)引用、軟引用、弱引用和虛引用的實戰(zhàn)指南
1、簡述
Java 的引用機(jī)制是垃圾回收(GC)體系中極為關(guān)鍵的一部分,不同引用類型代表不同的對象生命周期管理方式。合理使用引用類型,可以顯著優(yōu)化內(nèi)存利用率,提高系統(tǒng)穩(wěn)定性,尤其在緩存設(shè)計、資源管理和大規(guī)模數(shù)據(jù)處理場景中。
Java 從 JDK 1.2 起提供了四種引用級別:
- 強(qiáng)引用(Strong Reference)
- 軟引用(Soft Reference)
- 弱引用(Weak Reference)
- 虛引用(Phantom Reference)
本文將逐一講解它們的特點、內(nèi)存行為、適用場景,并提供實踐示例代碼。
2、引用機(jī)制
2.1 強(qiáng)引用(Strong Reference)
特點
- Java 默認(rèn)的引用方式,例如:
Object obj = new Object(); - 最強(qiáng)引用級別,只要存在強(qiáng)引用,GC 永不會回收該對象。
- 可能導(dǎo)致 OOM,如果強(qiáng)引用鏈無法斷開。
典型應(yīng)用
- 普通對象的創(chuàng)建與訪問。
- 業(yè)務(wù)邏輯中絕大部分引用。
2.2 軟引用(Soft Reference)
特點
- 內(nèi)存不足時,GC 會優(yōu)先回收軟引用指向的對象。
- 非內(nèi)存不足時,不會被回收。
- 適用于構(gòu)建內(nèi)存敏感緩存(如圖片緩存、數(shù)據(jù)緩沖區(qū)等)。
典型應(yīng)用
- Guava Cache、部分本地緩存策略。
- 內(nèi)存有限的移動端、IoT 程序的資源管理。
import java.lang.ref.SoftReference;
public class SoftRefDemo {
public static void main(String[] args) {
SoftReference<byte[]> softRef = new SoftReference<>(new byte[10 * 1024 * 1024]); // 10MB
System.out.println("Before GC: " + softRef.get());
System.gc();
System.out.println("After GC: " + softRef.get()); // 大概率存在
// 占用大量內(nèi)存觸發(fā)回收
try {
byte[] bigData = new byte[100 * 1024 * 1024];
} catch (Error e) {
System.out.println("內(nèi)存不足,軟引用對象被回收: " + softRef.get());
}
}
}
2.3 弱引用(Weak Reference)
特點
- 一旦 GC 執(zhí)行,無論內(nèi)存是否緊張,都會回收弱引用指向的對象。
- 弱引用典型特點:朝生暮死。
典型應(yīng)用
- 緩存(比軟引用更“短命”)。
- ThreadLocalMap 的 key(防止內(nèi)存泄漏)。
- 弱鍵 HashMap(WeakHashMap)。
import java.lang.ref.WeakReference;
public class WeakRefDemo {
public static void main(String[] args) {
WeakReference<String> weakRef = new WeakReference<>(new String("hello weak"));
System.out.println("Before GC: " + weakRef.get());
System.gc();
System.out.println("After GC: " + weakRef.get()); // 必定為 null
}
}
2.4 虛引用(Phantom Reference)
特點
- 最弱的引用類型:
phantomRef.get()永遠(yuǎn)返回 null。 - 必須結(jié)合 ReferenceQueue 使用。
- GC 回收對象前,會將虛引用放入隊列,用于資源清理。
應(yīng)用場景
- 替代
finalize(),實現(xiàn)更安全的資源釋放。 - 監(jiān)控對象回收過程。
- DirectByteBuffer 底層內(nèi)存釋放機(jī)制。
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class PhantomRefDemo {
public static void main(String[] args) throws InterruptedException {
ReferenceQueue<Object> queue = new ReferenceQueue<>();
Object obj = new Object();
PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);
System.out.println("Phantom get(): " + phantomRef.get()); // 永遠(yuǎn)是 null
obj = null;
System.gc();
Thread.sleep(100);
System.out.println("引用隊列是否有元素: " + (queue.poll() != null));
}
}
3、結(jié)合實際場景的應(yīng)用示例
3.1 使用軟引用構(gòu)建簡單緩存
import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SoftCache<K, V> {
private final Map<K, SoftReference<V>> cache = new ConcurrentHashMap<>();
public void put(K key, V value) {
cache.put(key, new SoftReference<>(value));
}
public V get(K key) {
SoftReference<V> ref = cache.get(key);
return ref == null ? null : ref.get(); // 若被回收則返回 null
}
}
3.2 WeakHashMap 自動回收 key
import java.util.WeakHashMap;
public class WeakHashMapDemo {
public static void main(String[] args) {
WeakHashMap<Object, String> map = new WeakHashMap<>();
Object key = new Object();
map.put(key, "value");
System.out.println("Before: " + map);
key = null;
System.gc();
try { Thread.sleep(100); } catch (Exception ignored) {}
System.out.println("After: " + map);
}
}
4、總結(jié)
- 強(qiáng)引用:正常使用,生命周期最長
- 軟引用:適合可回收緩存,避免 OOM
- 弱引用:適合避免內(nèi)存泄漏,如 WeakHashMap、ThreadLocal
- 虛引用:適用于對象回收監(jiān)聽,資源釋放管理
掌握這四種引用方式,有助于在高性能、高并發(fā)系統(tǒng)中更精細(xì)地管理內(nèi)存,提高系統(tǒng)健壯性。
| 引用類型 | GC 回收時機(jī) | 是否可通過 get() 獲得對象 | 常見用途 |
|---|---|---|---|
| 強(qiáng)引用 | 永不回收 | 可以 | 普通對象 |
| 軟引用 | 內(nèi)存不足時回收 | 可以 | 緩存(內(nèi)存敏感) |
| 弱引用 | 一遇 GC 即回收 | 可以 | WeakHashMap、避免內(nèi)存泄漏 |
| 虛引用 | 回收前通知 | 不可以(always null) | 資源清理、監(jiān)控對象生命周期 |
以上就是Java引用機(jī)制之強(qiáng)引用、軟引用、弱引用和虛引用的實戰(zhàn)指南的詳細(xì)內(nèi)容,更多關(guān)于Java強(qiáng)引用、軟引用、弱引用和虛引用的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用concurrentHashMap如何實現(xiàn)緩存
文章介紹了使用ConcurrentHashMap實現(xiàn)緩存的線程安全性和初始化方法,以及如何處理高并發(fā)場景下的緩存清理和數(shù)據(jù)一致性問題,包括分桶、使用ConcurrentLinkedQueue以及使用CountDownLatch來確保緩存數(shù)據(jù)的不丟失2025-02-02
springmvc項目使用@Valid+BindingResult遇到的問題
這篇文章主要介紹了springmvc項目使用@Valid+BindingResult遇到的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
httpclient staleConnectionCheckEnabled獲取連接流程解析
這篇文章主要為大家介紹了httpclient staleConnectionCheckEnabled獲取連接流程示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
java發(fā)起http請求調(diào)用post與get接口的方法實例
在實際開發(fā)過程中,我們經(jīng)常需要調(diào)用對方提供的接口或測試自己寫的接口是否合適,下面這篇文章主要給大家介紹了關(guān)于java發(fā)起http請求調(diào)用post與get接口的相關(guān)資料,需要的朋友可以參考下2022-08-08
Java同步鎖synchronized用法的最全總結(jié)
這篇文章主要介紹了Java同步鎖synchronized用法的最全總結(jié),需要的朋友可以參考下,文章詳細(xì)講解了Java同步鎖Synchronized的使用方法和需要注意的點,希望對你有所幫助2023-03-03
云IDE:Eclipse Che:Eclipse下一代IDE(推薦)
這篇文章主要介紹了云IDE:Eclipse Che:Eclipse下一代IDE,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09

