一文詳解jvm中的引用類型
1.強引用
一個對象A被局部變量、靜態(tài)變量引用了就產生了強引用。因為局部變量、靜態(tài)變量都是被GC Root對象關聯(lián)上的,所以被引用的對象A,就在GC Root的引用鏈上了。只要這一層關系存在,對象A就不會被垃圾回收器回收。所以只要方法不退出,局部變量就會保存當前對象A的地址,該對象就不會被回收。
public static void main(String[] args) { ArrayList<Object> objects = new ArrayList<>(); while (true) { //以下兩行代碼產生了兩個引用關系,1.bytes變量 到 new byte[1024 * 1024]; 這個字節(jié)數(shù)組的引用關系,這也是一個強引用 byte[] bytes = new byte[1024 * 1024]; //2. objects集合對象 到 字節(jié)數(shù)組的關系,也是強引用 objects.add(bytes); //每一輪while循環(huán)結束后,第一個引用關系就斷開了。 //但第二個引用關系沒有斷開!所以 bytes數(shù)組1mb大小的內存空間是不會被回收的。 //這樣就會導致每輪循環(huán)內存中增加1mb的數(shù)據(jù),而且不能被回收 } }
最后一次垃圾回收:回收前7873k,回收后7831k。回收前后內存差不多。說明有大量強引用在,而強引用不能被回收。最終內存不夠用而報錯。
2.軟引用
由于軟引用允許垃圾回收器在內存不足時回收對象。所以軟引用放的對象一般都不是很重要的對象,否則內存不足時,這個對象一被回收,某些核心數(shù)據(jù)就沒了。主要應用場景在緩存里面。
public static void main(String[] args) { ArrayList<SoftReference> objects = new ArrayList<>(); for (int i = 0; i < 10; i++) { byte[] bytes = new byte[1024 * 1024]; //軟引用 SoftReference<byte[]> softReference = new SoftReference<>(bytes); //將軟引用對象放入集合中 objects.add(softReference); System.out.println(i); } for (SoftReference softReference : objects) {//打印一下沒有被回收的軟引用 System.out.println(softReference.get()); } }
注:這里設置了堆內存10mb(由于還要其他強引用占用空間,所以存不下10個1mb的字節(jié)數(shù)組),且打印垃圾回收日志
說明:可以看到前七次沒有進行垃圾回收,在到下標為6時,進行垃圾回收,這個時候就會把所有軟引用對象全部回收,前七個對象沒有了。最后再放入7-9三個字節(jié)數(shù)組對象。
最終打印集合:前七個為null(被回收了),只有后三個了。
注:這種機制很適合緩存,因為就算緩存中軟引用的數(shù)據(jù)因為內存不足被回收了,也可以去數(shù)據(jù)庫中查詢數(shù)據(jù)。
3.弱引用
弱引用的生命周期比軟引用更短,無論內存是否充足,只要垃圾回收器開始工作,弱引用關聯(lián)的對象都會被回收。弱引用適用于實現(xiàn)可以隨時被回收的緩存數(shù)據(jù),因為它不受內存狀況的影響。
null null null null null null null null null [B@4eec7777 進程已結束,退出代碼0
執(zhí)行結果:前九個為空,最后一個由于強引用存在,沒有被回收。
4.虛引用
虛引用是最弱的一種引用關系,如果一個對象僅持有虛引用,那么它就和沒有任何引用一樣,它隨時可能會被回收,在 JDK1.2 之后,用 PhantomReference 類來表示,通過查看這個類的源碼,發(fā)現(xiàn)它只有一個構造函數(shù)和一個 get() 方法,而且它的 get() 方法僅僅是返回一個null,也就是說將永遠無法通過虛引用來獲取對象,虛引用必須要和 ReferenceQueue 引用隊列一起使用。
如果一個對象只具有虛引用,那么它就和沒有任何引用一樣,隨時會被JVM當作垃圾進行GC。
附:引用類型與內存管理
了解引用類型對于正確管理內存至關重要。雖然Java具有自動內存管理機制,但如果不正確使用引用類型,仍然可能會導致內存泄漏或者內存溢出等問題。以下是一些注意事項:
避免過多使用強引用:過多的強引用可能會導致內存占用過高,因此應盡量使用弱引用或軟引用來管理對象。
及時釋放不再需要的引用:當對象不再需要時,應及時釋放其引用,以便垃圾回收器可以回收對象并釋放內存。
注意循環(huán)引用:循環(huán)引用可能導致對象無法被回收,從而造成內存泄漏。在設計數(shù)據(jù)結構時,應特別注意避免出現(xiàn)循環(huán)引用。
總結
到此這篇關于jvm中引用類型的文章就介紹到這了,更多相關jvm引用類型內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot從yml配置文件中讀常用參數(shù)值實例方法
在本篇文章里小編給大家整理了關于SpringBoot從yml配置文件中讀常用參數(shù)值實例方法,有需要的朋友們學習下。2019-12-122020新版idea創(chuàng)建項目沒有javaEE 沒有Web選項的完美解決方法
這篇文章主要介紹了2020新版idea創(chuàng)建項目沒有javaEE 沒有Web選項的完美解決方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09使用RabbitMQ實現(xiàn)延時消息自動取消的案例詳解
這篇文章主要介紹了使用RabbitMQ實現(xiàn)延時消息自動取消的簡單案例,案例代碼包括導包的過程和相關配置文件,本文結合代碼給大家講解的非常詳細,需要的朋友可以參考下2024-03-03Spring?Boot中使用Spring?Retry重試框架的操作方法
這篇文章主要介紹了Spring?Retry?在SpringBoot?中的應用,介紹了RetryTemplate配置的時候,需要設置的重試策略和退避策略,需要的朋友可以參考下2022-04-04Java class文件格式之常量池_動力節(jié)點Java學院整理
這篇文章主要為大家詳細介紹了Java class文件格式之常量池的相關資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06如何使用會話Cookie和Java實現(xiàn)JWT身份驗證
這篇文章主要介紹了如何使用會話Cookie和Java實現(xiàn)JWT身份驗證,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2021-03-03