JVM元空間Metaspace的內(nèi)存結(jié)構(gòu)

我們深入研究元空間的架構(gòu)。我們描述了各個層和組件弓叛,以及它們是如何協(xié)同工作的毕籽。

這對那些想要破解hotspotMetaspace或者至少真正理解內(nèi)存的去向以及為什么我們不能僅僅使用malloc的人來說是很有趣的睡榆。

與大多數(shù)其他非平凡的分配器一樣,元空間是在層中實現(xiàn)的。

在底部锭硼,內(nèi)存是在操作系統(tǒng)的大區(qū)域中分配的。在中間婴削,我們將這些區(qū)域分割成不太大的塊虫溜,然后交給類裝入器寄雀。

在頂部急膀,類裝入器將這些塊分割為調(diào)用程序代碼餐禁。

元空間的底層:虛擬空間列表VirtualSpaceList

VirtualSpaceList:
http://hg.openjdk.java.net/jdk/jdk11/file/1ddf9a99e4ad/src/hotspot/share/memory/metaspace/virtualSpaceList.hpp#l39

在最底層(在最粗的粒度上),Metaspace的內(nèi)存是保留的,并通過類似mmap(3)的虛擬內(nèi)存調(diào)用從操作系統(tǒng)按需提交內(nèi)存隅忿。這種情況發(fā)生在2MB大小的區(qū)域(在64位平臺上)。

這些映射區(qū)域作為節(jié)點保存在名為VirtualSpaceList的全局鏈接列表中弊仪。

每個節(jié)點管理一個高水位線颓鲜,將已提交的空間與仍然未提交的空間分開黍匾。當分配達到最高水位線時,將按需提交新頁面升薯。為了避免過于頻繁地調(diào)用操作系統(tǒng)莱褒,保留了一點空間。

直到節(jié)點完全用完為止涎劈。然后广凸,分配一個新節(jié)點并將其添加到列表中。舊節(jié)點正在“失效”蛛枚。

內(nèi)存是從名為MetaChunk的塊節(jié)點分配的谅海。它們有三種尺寸,分別命名為specialized蹦浦、small和medium—命名具有歷史意義—通常為1K/4K/64K

JVM元空間metaspace的內(nèi)存結(jié)構(gòu)

VirtualSpaceList及其節(jié)點是全局結(jié)構(gòu)扭吁,而Metachunk由一個類裝入器擁有。因此盲镶,VirtualSpaceList中的單個節(jié)點可能包含來自不同類裝入器的塊:

JVM元空間metaspace的內(nèi)存結(jié)構(gòu)

當一個類裝入器及其所有相關(guān)的類被卸載時侥袜,用于保存其類元數(shù)據(jù)的元空間將被釋放。所有現(xiàn)在可用的塊都添加到全局可用列表(ChunkManager):

JVM元空間metaspace的內(nèi)存結(jié)構(gòu)

這些塊被重用:如果另一個類裝入器開始加載類并分配元空間溉贿,則可能會給它一個空閑塊枫吧,而不是分配一個新的塊:

JVM元空間metaspace的內(nèi)存結(jié)構(gòu)

Metaspace中間層:Metachunk

類裝入器從Metaspace請求內(nèi)存以獲取一段元數(shù)據(jù)(通常是少量的,大約幾十或幾百個字節(jié))顽照,比如200個字節(jié)由蘑。它將得到一個Metachunk——一塊通常比請求的內(nèi)存大得多的內(nèi)存。

為什么代兵?因為直接從全局VirtualSpaceList分配內(nèi)存非常昂貴尼酿。VirtualSpaceList是一個全局結(jié)構(gòu),需要鎖定植影。我們不想經(jīng)常這樣做裳擎,所以會給加載器一塊更大的內(nèi)存——這個Metachunk——加載程序?qū)⑹褂盟斓貪M足將來的分配,同時不鎖定其他加載程序思币。只有當塊用完時鹿响,加載程序才會再次困擾全局VirtualSpaceList。

元空間分配器如何決定要交給加載器的塊有多大谷饿?好吧惶我,都是猜測:

  • 新啟動的標準加載程序?qū)@得小的4K塊,直到達到任意閾值(4)博投,在該閾值時绸贡,元空間分配器明顯地失去了耐心,并開始給加載程序提供更大的64K塊。
  • 引導類加載器被稱為加載程序听怕,它傾向于加載許多類捧挺。所以分配器從一開始就給它一個巨大的塊(4M)。這可以通過InitialBootClassLoaderMetaspaceSize進行調(diào)整尿瞭。
  • 反射類加載器(jdk.internal.reflect.DelegatingClassLoader)和匿名類的類裝入器3已知只能加載一個類闽烙。因此,他們從一開始就得到非常小的(1K)塊声搁,因為假設(shè)他們很快就不再需要元空間黑竞,再給他們?nèi)魏螙|西都是浪費。

請注意酥艳,整個優(yōu)化——在假定加載程序很快就會需要它的情況下摊溶,為它提供比當前需要更多的空間——是對該加載程序未來分配行為的賭注,可能是正確的充石,也可能是不正確的莫换。一旦分配器給它們一大塊,它們就可能停止加載骤铃。

This is basically like feeding cats, or small children. The small ones you give a small amount of food on the plate, for the large ones you pile it on, and both cats and children may surprise you at any moment by dropping the spoon (the children, not the cats) and walking away, leaving half-eaten plates of memory behind. The penalty for guessing wrong is wasted memory.

Metaspace上層:元塊Metablock

Metachunk中拉岁,我們有第二個類裝入器本地分配器。它將元塊分割成小的分配單元惰爬。這些單元稱為元塊喊暖,是傳遞給調(diào)用者的實際單元(例如,元塊包含一個InstanceKlass)撕瞧。

此類裝入器本地分配器可以是原始的陵叽,因此速度很快:

類元數(shù)據(jù)的生存期被綁定到類加載器上,當類裝入器死亡時丛版,它將被批量釋放巩掺。因此,JVM不需要關(guān)心釋放隨機元塊4页畦。與一般用途的malloc(3)分配器不同胖替。

讓我們來檢查一下Metachunk:

JVM元空間metaspace的內(nèi)存結(jié)構(gòu)

當它出生時,它只包含頭豫缨。隨后的分配只是在頂部分配独令。由于整塊元數(shù)據(jù)都可以被釋放,所以不能再依賴于整塊的分配好芭。

注意當前塊的“未使用”部分:由于塊屬于一個類裝入器燃箭,所以該部分只能由同一個裝入器使用。如果加載程序停止加載類舍败,那么這個空間實際上是浪費了招狸。

ClassloaderData和ClassLoaderMetaspace

類裝入器將其本機表示形式保存在名為ClassLoaderData的本機結(jié)構(gòu)中碗硬。

該結(jié)構(gòu)引用了一個ClassLoaderMetaspace結(jié)構(gòu),該結(jié)構(gòu)保存了該加載程序使用的所有元塊的列表瓢颅。

當加載程序被卸載時,關(guān)聯(lián)的ClassLoaderData及其ClassLoaderMetaspace將被刪除弛说。這會將類裝入器使用的所有塊釋放到元空間空閑列表中挽懦。如果條件正確,可能會或不會導致內(nèi)存釋放到操作系統(tǒng)木人,請參閱:http://javakk.com/160.html

匿名類

類加載器數(shù)據(jù) != ClassLoaderMetaspace

注意我們一直在說“元空間內(nèi)存由它的類加載器擁有”——但這里我們有點撒謊信柿,這是一種簡化。隨著匿名類的增加醒第,情況變得更加復雜:

這些是為動態(tài)語言支持而生成的構(gòu)造渔嚷。當裝入器加載匿名類時,該類將獲得自己的獨立ClassLoaderData稠曼,其生存期與匿名類的生存期耦合形病,而不是宿主類裝入器(因此,可以在收集housing loader之前收集它及其關(guān)聯(lián)的元數(shù)據(jù))霞幅。這意味著類裝入器對所有正常加載的類都有一個主類裝入器數(shù)據(jù)漠吻,而每個匿名類都有一個輔助類裝入器數(shù)據(jù)結(jié)構(gòu)。

這種分離的目的是為了不必要地延長Lambdas和方法句柄之類的元空間分配的壽命司恳。

JVM元空間metaspace的內(nèi)存結(jié)構(gòu)

那么途乃,再說一次:內(nèi)存何時返回操作系統(tǒng)?

讓我們再看看內(nèi)存何時返回操作系統(tǒng)扔傅。我們現(xiàn)在可以比第1部分末尾更詳細地回答這個問題:

當一個VirtualSpaceListNode中的所有塊碰巧是空閑的時耍共,該節(jié)點本身將被移除。該節(jié)點將從VirtualSpaceList中刪除猎塞。它的空閑塊從Metaspace空閑列表中移除试读。節(jié)點被取消映射,其內(nèi)存返回給操作系統(tǒng)邢享。節(jié)點被“清除”鹏往。

JVM元空間metaspace的內(nèi)存結(jié)構(gòu)

為了使一個節(jié)點中的所有塊都是空閑的,擁有這些塊的所有類裝入器都必須已經(jīng)死亡骇塘。

這是否可能在很大程度上取決于碎片化:

一個節(jié)點的大小是2MB伊履;塊的大小從1K-64K不等;通常每個節(jié)點的負載是150-200塊款违。如果這些塊都是由一個類裝入器分配的唐瀑,那么收集該裝入器將釋放節(jié)點并將其內(nèi)存釋放給操作系統(tǒng)。

但是插爹,如果這些塊由具有不同生命周期的不同類裝入器擁有哄辣,則不會釋放任何內(nèi)容请梢。當我們處理許多小類裝入器(例如匿名類的裝入器或反射委托器)時,可能會出現(xiàn)這種情況力穗。

另外毅弧,請注意,部分Metaspace(壓縮類空間)將永遠不會釋放回操作系統(tǒng)当窗。

  • 內(nèi)存由操作系統(tǒng)在2MB大小的區(qū)域中保留够坐,并保存在全局鏈接列表中。這些地區(qū)承諾按需提供服務崖面。
  • 這些區(qū)域被分割成塊元咙,然后交給類裝入器。塊屬于一個類裝入器巫员。
  • 塊被進一步分割成微小的分配庶香,稱為塊。這些是分發(fā)給呼叫者的分配單元简识。
  • 當一個全局塊被重新使用時赶掖,它擁有一個全局塊。部分內(nèi)存可能會被釋放到操作系統(tǒng)中财异,但這在很大程度上取決于碎片化和運氣倘零。

文章來源:http://javakk.com/395.html
也歡迎大家關(guān)注我的公眾號【Java老K】獲取更多干貨

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市戳寸,隨后出現(xiàn)的幾起案子呈驶,更是在濱河造成了極大的恐慌,老刑警劉巖疫鹊,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袖瞻,死亡現(xiàn)場離奇詭異,居然都是意外死亡拆吆,警方通過查閱死者的電腦和手機聋迎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枣耀,“玉大人霉晕,你說我怎么就攤上這事±剔龋” “怎么了牺堰?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長颅围。 經(jīng)常有香客問我伟葫,道長,這世上最難降的妖魔是什么院促? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任筏养,我火速辦了婚禮斧抱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渐溶。我一直安慰自己辉浦,他們只是感情好,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布茎辐。 她就那樣靜靜地躺著盏浙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荔茬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天竹海,我揣著相機與錄音慕蔚,去河邊找鬼。 笑死斋配,一個胖子當著我的面吹牛孔飒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播艰争,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼坏瞄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了甩卓?” 一聲冷哼從身側(cè)響起鸠匀,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逾柿,沒想到半個月后缀棍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡机错,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年爬范,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弱匪。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡青瀑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出萧诫,到底是詐尸還是另有隱情斥难,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布财搁,位于F島的核電站蘸炸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏尖奔。R本人自食惡果不足惜搭儒,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一穷当、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧淹禾,春花似錦馁菜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至毁习,卻和暖如春智嚷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纺且。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工盏道, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人载碌。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓猜嘱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嫁艇。 傳聞我的和親對象是個殘疾皇子朗伶,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351