日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java元空间扩容_JVM元空间(Metaspace)

發(fā)布時間:2025/3/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java元空间扩容_JVM元空间(Metaspace) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

從方法區(qū)(PermGen)到元空間(Metaspace)

方法區(qū)(PermGen)

JDK1.8以前的HotSpot JVM有方法區(qū),也叫永久代(permanent generation)。

方法區(qū)用于存放已被虛擬機加載的類信息、常量、靜態(tài)變量,即編譯器編譯后的代碼。

方法區(qū)是一片連續(xù)的堆空間,通過-XX:MaxPermSize來設(shè)定永久代最大可分配空間,當(dāng)JVM加載的類信息容量超過了這個值,會報OOM:PermGen錯誤。

永久代的GC是和老年代(old generation)捆綁在一起的,無論誰滿了,都會觸發(fā)永久代和老年代的垃圾收集。

JDK1.7開始了方法區(qū)的部分移除:符號引用(Symbols)移至native heap,字面量(interned strings)和靜態(tài)變量(class statics)移至java heap。

為什么要用Metaspace替代方法區(qū)

隨著動態(tài)類加載的情況越來越多,這塊內(nèi)存變得不太可控,如果設(shè)置小了,系統(tǒng)運行過程中就容易出現(xiàn)內(nèi)存溢出,設(shè)置大了又浪費內(nèi)存。

Metaspace的組成

Metaspace由兩大部分組成:Klass Metaspace和NoKlass Metaspace。

Klass Metaspace

Klass Metaspace就是用來存klass的,就是class文件在jvm里的運行時數(shù)據(jù)結(jié)構(gòu)(不過我們看到的類似A.class其實是存在heap里的,是java.lang.Class的對象實例)。

這部分默認(rèn)放在Compressed Class Pointer Space中,是一塊連續(xù)的內(nèi)存區(qū)域,緊接著Heap,和之前的perm一樣。通過-XX:CompressedClassSpaceSize來控制這塊內(nèi)存的大小,默認(rèn)是1G。

下圖展示了對象的存儲模型,_mark是對象的Mark Word,_klass是元數(shù)據(jù)指針

Compressed Class Pointer Space不是必須有的,如果設(shè)置了-XX:-UseCompressedClassPointers,或者-Xmx設(shè)置大于32G,就不會有這塊內(nèi)存,這種情況下klass都會存在NoKlass Metaspace里。

NoKlass Metaspace

NoKlass Metaspace專門來存klass相關(guān)的其他的內(nèi)容,比如method,constantPool等,可以由多塊不連續(xù)的內(nèi)存組成。

這塊內(nèi)存是必須的,雖然叫做NoKlass Metaspace,但是也其實可以存klass的內(nèi)容,上面已經(jīng)提到了對應(yīng)場景。

NoKlass Metaspace在本地內(nèi)存中分配。

指針壓縮

64位平臺上默認(rèn)打開

設(shè)置-XX:+UseCompressedOops壓縮對象指針, oops指的是普通對象指針(ordinary object pointers), 會被壓縮成32位。

設(shè)置-XX:+UseCompressedClassPointers壓縮類指針,會被壓縮成32位。

Metaspace內(nèi)存管理

在metaspace中,類和其元數(shù)據(jù)的生命周期與其對應(yīng)的類加載器相同,只要類的類加載器是存活的,在Metaspace中的類元數(shù)據(jù)也是存活的,不能被回收。

每個加載器有單獨的存儲空間。

省掉了GC掃描及壓縮的時間。

當(dāng)GC發(fā)現(xiàn)某個類加載器不再存活了,會把對應(yīng)的空間整個回收。

Metaspace VM使用一個塊分配器(chunking allocator)來管理Metaspace空間的內(nèi)存分配。塊的大小依賴于類加載器的類型。

Metaspace VM中有一個全局的可使用的塊列表(a global free list of chunks)。當(dāng)類加載器需要一個塊的時候,類加載器從全局塊列表中取出一個塊,添加到它自己維護的塊列表中。當(dāng)類加載器死亡,它的塊將會被釋放,歸還給全局的塊列表。

塊(chunk)會進一步被劃分成blocks,每個block存儲一個元數(shù)據(jù)單元(a unit of metadata)。Chunk中Blocks的是分配線性的(pointer bump)。這些chunks被分配在內(nèi)存映射空間(memory mapped(mmapped) spaces)之外。在一個全局的虛擬內(nèi)存映射空間(global virtual mmapped spaces)的鏈表,當(dāng)任何虛擬空間變?yōu)榭諘r,就將該虛擬空間歸還回操作系統(tǒng)。

上面這幅圖展示了Metaspace使用metachunks在mmapeded virual spaces分配的情形。

metaspace的主要參數(shù)

MetaspaceSize

MaxMetaspaceSize

CompressedClassSpaceSize

MinMetaspaceExpansion

MaxMetaspaceExpansion

MinMetaspaceFreeRatio

MaxMetaspaceFreeRatio

UseLargePagesInMetaspace

InitialBootClassLoaderMetaspaceSize

MetaspaceSize

metaspaceGC發(fā)生的初始閾值,也是最小閾值,默認(rèn)20.8M左右,與之對比的主要是指Klass Metaspace與NoKlass Metaspace兩塊committed的內(nèi)存和。

觸發(fā)metaspaceGC的閾值是不斷變化的:當(dāng)metaspace使用的內(nèi)存接近閾值時,會嘗試增大閾值。metaspaceGC后也會調(diào)整閾值。

MaxMetaspaceSize

由于metaspace大部分在本地內(nèi)存中分配,默認(rèn)基本是無窮大,但仍然受本地內(nèi)存大小的限制。為了防止metaspace被無止境使用,建議設(shè)置這個參數(shù)。

這個參數(shù)會限制metaspace(包括了Klass Metaspace以及NoKlass Metaspace)被committed的內(nèi)存大小,會保證committed的內(nèi)存不會超過這個值,一旦超過就會觸發(fā)GC。

和MaxPermSize的區(qū)別,根據(jù)MaxMetaspaceSize,并不會在jvm啟動的時候分配一塊這么大的內(nèi)存出來,而根據(jù)MaxPermSize分配的內(nèi)存則是固定大小。

CompressedClassSpaceSize

Compressed Class Pointer Space區(qū)域的大小,默認(rèn)1G。

如果設(shè)置了-XX:-UseCompressedClassPointers,或者-Xmx設(shè)置大于32G,則這個參數(shù)不生效。

MinMetaspaceExpansion

MinMetaspaceExpansion和MaxMetaspaceExpansion這兩個參數(shù)這兩個參數(shù)和擴容其實并沒有直接的關(guān)系,并不是為了增大committed的內(nèi)存。

主要是在比較特殊的場景下救急使用,增大觸發(fā)metaspace GC的閾值,延遲GC的發(fā)生。

默認(rèn)332.8K,增大觸發(fā)metaspace GC閾值的最小要求。

如果需要分配的內(nèi)存小于MinMetaspaceExpansion,則將metaspace GC的閾值提升MinMetaspaceExpansion。

MaxMetaspaceExpansion

默認(rèn)5.2M,增大觸發(fā)metaspace GC閾值的最大要求。

如果需要分配的內(nèi)存大于MinMetaspaceExpansion但是小于MaxMetaspaceExpansion,那增量就是MaxMetaspaceExpansion。

如果需要分配的內(nèi)存超過了MaxMetaspaceExpansion,那增量就是MinMetaspaceExpansion加上要分配的內(nèi)存大小

注:每次分配只會給對應(yīng)的線程一次擴展觸發(fā)metaspace GC閾值的機會,如果擴展了,但是還不能分配,那就只能等著做GC了。

MinMetaspaceFreeRatio

MinMetaspaceFreeRatio和下面的MaxMetaspaceFreeRatio,主要是影響觸發(fā)metaspaceGC的閾值。

默認(rèn)40,表示每次GC完之后,如果metaspace內(nèi)存的空閑比例小于MinMetaspaceFreeRatio%,那么將嘗試做擴容,增大觸發(fā)metaspaceGC的閾值。

不過這個增量至少是MinMetaspaceExpansion才會做,不然不會增加這個閾值。

這個參數(shù)主要是為了避免觸發(fā)metaspaceGC的閾值和gc之后committed的內(nèi)存的量比較接近,于是將這個閾值進行擴大。

注:這里不用gc之后used的量來算,主要是擔(dān)心可能出現(xiàn)committed的量超過了觸發(fā)metaspaceGC的閾值,這種情況一旦發(fā)生會很危險,會不斷做gc,這應(yīng)該是jdk8在某個版本之后才修復(fù)的bug

MaxMetaspaceFreeRatio

默認(rèn)70,這個參數(shù)和上面的參數(shù)基本是相反的,是為了避免觸發(fā)metaspaceGC的閾值過大,而想對這個值進行縮小。

這個參數(shù)在gc之后committed的內(nèi)存比較小的時候并且離觸發(fā)metaspaceGC的閾值比較遠(yuǎn)的時候,調(diào)整會比較明顯。

UseLargePagesInMetaspace

默認(rèn)false,這個參數(shù)是說是否在metaspace里使用LargePage,一般情況下我們使用4KB的page size,這個參數(shù)依賴于UseLargePages這個參數(shù)開啟,不過這個參數(shù)我們一般不開。

InitialBootClassLoaderMetaspaceSize

64位下默認(rèn)4M,32位下默認(rèn)2200K,metasapce前面已經(jīng)提到主要分了兩大塊,Klass Metaspace以及NoKlass Metaspace,而NoKlass Metaspace是由一塊塊內(nèi)存組合起來的,這個參數(shù)決定了NoKlass Metaspace的第一個內(nèi)存Block的大小,即2*InitialBootClassLoaderMetaspaceSize,同時為bootstrapClassLoader的第一塊內(nèi)存chunk分配了InitialBootClassLoaderMetaspaceSize的大小

jstat里的metaspace字段

我們看GC是否異常,除了通過GC日志來做分析之外,我們還可以通過jstat這樣的工具展示的數(shù)據(jù)來分析,前面我公眾號里有篇文章介紹了jstat這塊的實現(xiàn),有興趣的可以到我的公眾號你假笨里去翻閱下jstat的這篇文章。

我們通過jstat可以看到metaspace相關(guān)的這么一些指標(biāo),分別是M,CCS,MC,MU,CCSC,CCSU,MCMN,MCMX,CCSMN,CCSMX

MC & MU & CCSC & CCSU

MC表示Klass Metaspace以及NoKlass Metaspace兩者總共committed的內(nèi)存大小,單位是KB,雖然從上面的定義里我們看到了是capacity,但是實質(zhì)上計算的時候并不是capacity,而是committed,這個是要注意的

MU這個無可厚非,說的就是Klass Metaspace以及NoKlass Metaspace兩者已經(jīng)使用了的內(nèi)存大小

CCSC表示的是Klass Metaspace的已經(jīng)被commit的內(nèi)存大小,單位也是KB

CCSU表示Klass Metaspace的已經(jīng)被使用的內(nèi)存大小

M & CCS

M表示的是Klass Metaspace以及NoKlass Metaspace兩者總共的使用率,其實可以根據(jù)上面的四個指標(biāo)算出來,即(CCSU+MU)/(CCSC+MC)

CCS表示的是NoKlass Metaspace的使用率,也就是CCSU/CCSC算出來的

PS:所以我們有時候看到M的值達到了90%以上,其實這個并不一定說明metaspace用了很多了,因為內(nèi)存是慢慢commit的,所以我們的分母是慢慢變大的,不過當(dāng)我們committed到一定量的時候就不會再增長了

MCMN & MCMX & CCSMN & CCSMX

MCMN和CCSMN這兩個值可以忽略,一直都是0

MCMX表示Klass Metaspace以及NoKlass Metaspace兩者總共的reserved的內(nèi)存大小,比如默認(rèn)情況下Klass Metaspace是通過CompressedClassSpaceSize這個參數(shù)來reserved 1G的內(nèi)存,NoKlass Metaspace默認(rèn)reserved的內(nèi)存大小是2* InitialBootClassLoaderMetaspaceSize

CCSMX表示Klass Metaspace reserved的內(nèi)存大小

總結(jié)

以上是生活随笔為你收集整理的java元空间扩容_JVM元空间(Metaspace)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。