JVM的內(nèi)存回收及常見算法小結(jié)
什么樣的對象應(yīng)該被回收?
某個對象不再被棧直接或間接地引用,此時就應(yīng)該被回收了。

o被指向null的時候,new Object()創(chuàng)建的對象就不在被棧引用了,可以被回收。

p1和personList均不再指向第一個Person對象的時候,第一個Person對象、list對象可以被回收。

經(jīng)歷前面的幾個階段,內(nèi)存引用是這樣的情況。

p1 = null后,p1曾經(jīng)指向的對象雖然不再被棧直接引用,但是仍然間接通過persons引用。

此時p1指向的對象和list指向的對象都可以被回收了。
怎么樣確定哪些需要回收?
對我們?nèi)匀恍枰褂玫膶ο筮M行標記,回收沒有標記的對象。

以此為例,如何進行標記的呢?

垃圾回收進行之前,所有對象的標記位是0

如果僅僅標記棧直接引用的對象,p1就會被回收,但是p1間接被list引用,因此也被標記為1

標記算法
-Stop the World(GC Root可達性算法)
在進行上面的標記過程的時候,如果有新的對象被創(chuàng)建,而剛好被標記過程錯過的時候,就可能錯誤地把有用的對象給回收掉,因為標記位是0.因此,Stop the World正如其名,將應(yīng)用的核心線程停掉,開始專心標記。
-引用計數(shù)法
對對象進行引用數(shù)量的標記,沒有引用的對象標記是0,有引用的對象標記是引用數(shù)量。清除標記為0的對象即可。但是引用計數(shù)法有個問題,無法解決循環(huán)引用的問題,導(dǎo)致內(nèi)存泄露。

這里聲明一個對象,內(nèi)部包含一個跟自己一個類型的成員變量。


在執(zhí)行第五行之前,兩個對象的引用計數(shù)均為2,各自引用,加上n1和n2.

執(zhí)行完第五六行以后,按道理,棧上已經(jīng)不在引用這兩個對象,可以被回收了,但是因為n1和n2相互引用,導(dǎo)致引用計數(shù)為1,無法正?;厥?。
清除算法
一般清除算法:直接將未標記的對象清理掉

經(jīng)過清理,未標記的對象被回收。

但是存在內(nèi)存碎片化的問題,只能從間隙處繼續(xù)分配內(nèi)存,

存在內(nèi)存不連續(xù)的問題,內(nèi)存空間浪費嚴重,容易oom
清除-整理算法:先清除沒有標記的對象,然后將剩余的存活對象進行整理,讓內(nèi)存空間更加連續(xù)。

就是代價比較高,幾乎需要移動所有的對象。
復(fù)制-清除算法:將活躍的對象復(fù)制到另一個內(nèi)存區(qū)域,然后清除當(dāng)前區(qū)域的所有對象!

完成復(fù)制后,清除原有的區(qū)域

這種算法的弊端就是需要更多的內(nèi)存空間。
常見的GC類型
| GC類別 | 新生代垃圾回收 | 老年代垃圾回收 | 特點 |
| Serial GC | 標記-復(fù)制&清除 | 標記-清除&整理 | Stop the World
使用單個線程處理 適合小應(yīng)用 |
| Parallel GC | Java 8默認垃圾回收器
Stop the World 使用多個線程處理 | ||
| CMS GC | 標記-復(fù)制&清除
(Stop the World) | 接近并行的標記-清除
初始標記->并發(fā)標記 -> 并發(fā)預(yù)清理->可中斷預(yù)清理->重新標記->并發(fā)清除->并發(fā)重置 | |
| G1 GC | 更細粒度的邏輯分區(qū),更小的停頓時間 采用復(fù)制&整理-清理的方式,優(yōu)先回收垃圾最多的區(qū)域 對字符串的合并整理,多個相同的字符串合并到一起,移除冗余字符串對象 | -XX:UseStringDeduplication | |
| Z GC | 不在維護映射,而是對象上保持一個標記來表示活躍對象 僅支持64位系統(tǒng) 采用重定位解決內(nèi)存碎片化問題 | Java 15 | |
到此這篇關(guān)于JVM的內(nèi)存回收及常見算法的文章就介紹到這了,更多相關(guān)JVM的內(nèi)存回收內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis-plus的selectPage()分頁查詢不生效問題解決
本文主要介紹了Mybatis-plus的selectPage()分頁查詢不生效問題解決,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
Java 數(shù)據(jù)結(jié)構(gòu)進階二叉樹題集上
二叉樹可以簡單理解為對于一個節(jié)點來說,最多擁有一個上級節(jié)點,同時最多具備左右兩個下級節(jié)點的數(shù)據(jù)結(jié)構(gòu)。本文將帶你通過實際題目來熟練掌握2022-04-04
JavaSE學(xué)習(xí)之內(nèi)部類及常用API
這篇文章主要介紹了JavaSE中的內(nèi)部類和幾個常用的API,文中的示例代碼介紹詳細,對我們學(xué)習(xí)JavaSEI有一定的幫助,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2021-12-12
springboot接收http請求,解決參數(shù)中+號變成空格的問題
這篇文章主要介紹了springboot接收http請求,解決參數(shù)中+號變成空格的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08
SpringBoot 使用WebSocket功能(實現(xiàn)步驟)
本文通過詳細步驟介紹了SpringBoot 使用WebSocket功能,首先需要導(dǎo)入WebSocket坐標,編寫WebSocket配置類,用于注冊WebSocket的Bean,結(jié)合示例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧2024-02-02
Springboot之restTemplate配置及使用方式
這篇文章主要介紹了Springboot之restTemplate配置及使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04
mybatis+springboot發(fā)布postgresql數(shù)據(jù)的實現(xiàn)
本文主要介紹了mybatis+springboot發(fā)布postgresql數(shù)據(jù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11

