??
作者簡介:努力的clz ,一個努力編程的菜鳥??????
???
文章專欄:《JVM 學(xué)習(xí)筆記》 ,本專欄會專門記錄博主在學(xué)習(xí)JVM
中學(xué)習(xí)的知識點,以及遇到的問題。
???
文章詳情: 本篇博客是學(xué)習(xí) 【狂神說Java】JVM快速入門篇 的學(xué)習(xí)筆記,關(guān)于GC垃圾回收機制 (堆內(nèi)存結(jié)構(gòu)、GC分類、四大垃圾回收算法)
知識點的學(xué)習(xí)總結(jié),由于這三個知識點的相互聯(lián)系,所以放在一起進(jìn)行描述介紹。
??????????????????????? ?????? ???????? ???????????????? ???? ????????????????????
?
一、堆
1. JVM體系結(jié)構(gòu)圖
簡單回顧下
JVM體系結(jié)構(gòu)圖
,后續(xù)將針對堆
進(jìn)行展開學(xué)習(xí)。
?
2. 堆
Heap 堆,一個JVM實例只存在一個堆內(nèi)存,堆內(nèi)存的大小是可以調(diào)節(jié)的;
類加載器讀取了類文件后,需要 把類,方法,常變量放到堆內(nèi)存中,保存所有引用類型的真實信息,以方便執(zhí)行器執(zhí)行;
?
堆內(nèi)存邏輯上分為三部分:新生,養(yǎng)老,永久 (元空間 : JDK8 以后名稱)
GC垃圾回收主要是在 新生區(qū)和養(yǎng)老區(qū),又分為 輕GC 和 重GC。
如果內(nèi)存滿了,OOM 堆內(nèi)存不夠,就會導(dǎo)致java.lang.OutOfMemoryError: Java heap space
堆內(nèi)存結(jié)構(gòu) | |
---|---|
新生區(qū) Young Generation Space | Young/New |
養(yǎng)老區(qū) Tenure generation space | Old/Tenure |
永久區(qū) Permanent Space | Perm |
?
新生區(qū):
新生區(qū)是類誕生,成長,消亡的區(qū)域,一個類在這里產(chǎn)生,應(yīng)用,最后被垃圾回收器收集,結(jié)束生命。
新生區(qū)又分為兩部分:伊甸區(qū)(Eden Space)和幸存者區(qū)(Survivor Space),所有的類都是在伊甸區(qū)被new出來的;
幸存區(qū)有兩個:0區(qū) 和 1區(qū);
當(dāng)伊甸園的空間用完時,程序又需要創(chuàng)建對象,JVM的垃圾回收器將對伊甸園區(qū)進(jìn)行垃圾回收 (Minor GC)。
?
養(yǎng)老區(qū)
將伊甸園中的剩余對象移動到幸存0區(qū),若幸存0區(qū)也滿了,再對該區(qū)進(jìn)行垃圾回收,然后移動到1區(qū),那如果1區(qū)也滿了呢?
(這里幸存0區(qū)和1區(qū)是一個互相交替的過程)
就再移動到養(yǎng)老區(qū),若養(yǎng)老區(qū)也滿了,那么這個時候?qū)a(chǎn)生 MajorGC(Full GC),進(jìn)行養(yǎng)老區(qū)的內(nèi)存清理,若養(yǎng)老區(qū)執(zhí)行了Full GC 后發(fā)現(xiàn)依然無法進(jìn)行對象的保存,就會 產(chǎn)生OOM異?!癘utOfMemoryError ”。
如果出現(xiàn) java.lang.OutOfMemoryError:java heap space異常,說明Java虛擬機的堆內(nèi)存不夠,原因如下:
1、Java虛擬機的堆內(nèi)存設(shè)置不夠,可以通過參數(shù) -Xms(初始值大小),-Xmx(最大大?。﹣碚{(diào)整。
2、代碼中創(chuàng)建了 大量大對象,并且長時間不能被垃圾收集器收集(存在被引用)或者死循環(huán)了。
?
永久區(qū)(Perm):
? 永久存儲區(qū)是一個常駐內(nèi)存區(qū)域,用于存放JDK自身所攜帶的Class,Interface的元數(shù)據(jù),也就是說它存儲的是運行環(huán)境必須的類
信息,被裝載進(jìn)此區(qū)域的數(shù)據(jù)是不會被垃圾回收器回收掉的,關(guān)閉JVM才會釋放此區(qū)域所占用的內(nèi)存。
如果出現(xiàn) java.lang.OutOfMemoryError:PermGen space
,說明是 Java虛擬機對永久代Perm內(nèi)存設(shè)置不夠。一般出現(xiàn)這種情況,
都是程序啟動需要加載大量的第三方j(luò)ar包。
? 例如:在一個Tomcat下部署了太多的應(yīng)用?;蛘叽罅縿討B(tài)反射生成的類不斷被加載,最終導(dǎo)致Perm區(qū)被占滿。
Jdk1.6之前: 有永久代,常量池1.6在方法區(qū)
Jdk1.7: 有永久代,但是已經(jīng)逐步 “去永久代”,常量池1.7在堆
Jdk1.8及之后:無永久代,常量池1.8在元空間
?
二、GC分類
熟悉堆的三區(qū)結(jié)構(gòu)后,方可學(xué)習(xí)JVM垃圾回收機制。
記住GC口訣: 分代收集算法
次數(shù)頻繁Young區(qū),次數(shù)較少Old區(qū),基本不動Perm(永久區(qū))區(qū)
?
JVM在GC時,并非每次都對上面三個內(nèi)存區(qū)域一起回收的,大部分時候回收的都是新生代
GC安裝回收的區(qū)域分成兩種:普通GC(minor GC),全局GC(major GC or Full GC)
普通GC:只針對新生代的GC
全局GC:針對老年代的GC,偶爾伴隨對新生代的GC以及對永久代的GC
?
三、GC四大算法
1. 引用計數(shù)法
每個對象有一個引用計數(shù)器,當(dāng)對象被引用一次則計數(shù)器加1,當(dāng)對象引用失效一次,則計數(shù)器減1;
對于計數(shù)器為0的對象意味著是垃圾對象,可以被GC回收。
目前虛擬機基本都是采用 可達(dá)性算法
,從 GC Roots 作為起點開始搜索,那么整個連通圖中的對象里邊都是活對象,對于GC Roots 無法到達(dá)的對象變成了垃圾回收對象,隨時可被GC回收。
?
2. 復(fù)制算法
年輕代中使用的是
Minor GC
,采用的就是復(fù)制算法 (Copying)
?
好處:沒有內(nèi)存碎片,壞處:浪費內(nèi)存空間
劣勢:
1、他浪費了一半的內(nèi)存,這太要命了.
2、如果對象的存活率很高,我們可以極端一點,假設(shè)是100%存活,那么我們需要將所有對象都復(fù)制一遍,并將所有引用地址重置一遍。
復(fù)制這一工作所花費的時間,在對象存活率達(dá)到一定程度時,將會變的不可忽視,所以從以上描述不難看出。
復(fù)制算法要想使用,最起碼對象的存活率要非常低才行,而且最重要的是,我們必須要克服50%的內(nèi)存浪費。
?
3. 標(biāo)記清除(Mark-Sweep)
掃描(Mark):從根集合開始掃描,對存活的對象進(jìn)行標(biāo)記
?
清除(Sweep):掃描整個內(nèi)存空間,回收未標(biāo)記的對象,使用free-list記錄可用區(qū)域
優(yōu)點:不需要額外的空間;
缺點:兩次掃描,驗證浪費時間,會產(chǎn)生內(nèi)存碎片;
?
4. 標(biāo)記清除壓縮算法(Mark-Sweep-Compact)
進(jìn)一步優(yōu)化——標(biāo)記壓縮(Mark-Compact)
?
最終版本算法 —— 先標(biāo)記清除幾次,再進(jìn)行壓縮
?
總結(jié)
內(nèi)存效率:
復(fù)制算法 > 標(biāo)記清除算法 > 標(biāo)記整理算法 (時間復(fù)雜度)
?
內(nèi)存整齊度:復(fù)制算法 = 標(biāo)記整理算法 > 標(biāo)記清除算法
?
內(nèi)存利用率:標(biāo)記整理算法 = 標(biāo)記清除算法 > 復(fù)制算法
可以看出,效率上來說,復(fù)制算法是當(dāng)之無愧的老大,但是卻浪費了太多內(nèi)存,而為了盡量兼顧上面所提到的三個指標(biāo),標(biāo)記整理算法相對來說更平滑一些 , 但是效率上依然不盡如人意,它比復(fù)制算法多了一個標(biāo)記的階段,又比標(biāo)記清除多了一個整理內(nèi)存的過程。
?
【問】難道就沒有一種最優(yōu)算法嗎?
答案 : 無,沒有最好的算法,只有最合適的算法 —— GC: 分代收集算法
年輕代:
- 存活率低
- 使用復(fù)制算法
?
老年代:
- 區(qū)域大,存活率高
- 標(biāo)記清除(內(nèi)存碎片不是太多的時候) + 標(biāo)記壓縮混合
?
點擊可快速回到文章開頭:文章頂部 ????
文章來源:http://www.zghlxwxcb.cn/news/detail-418217.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-418217.html
到了這里,關(guān)于JVM學(xué)習(xí) GC垃圾回收機制 (堆內(nèi)存結(jié)構(gòu)、GC分類、四大垃圾回收算法)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!