眾所周知java8的新特性之一是完全刪除了永久生成(PermGen)空間电媳,自jdk7發(fā)布以來骨坑,Oracle就已經宣布了這一點。例如绑谣,自jdk7以來,內部字符串已經從PermGen空間中刪除拗引。jdk8版本完成了它的退役借宵。本文將與大家分享到目前為止我們在PermGen繼任者:Metaspace
上發(fā)現的信息。我們還將比較hotspots1.7和hotspots1.8(b75)在執(zhí)行Java程序“泄漏”類元數據對象時的運行時行為矾削。一旦java8正式發(fā)布壤玫,圍繞Metaspace
的最終規(guī)范、調優(yōu)標志和文檔應該可以使用哼凯。
元空間Metaspace
一個新的記憶空間誕生了
jdk8熱點JVM現在使用本機內存來表示類元數據欲间,稱為Metaspace
;類似于oraclejrockit
和IBMJVM java.lang.OutOfMemoryError:PermGen
空間問題断部,無需再調整和監(jiān)視此內存空間…不要太快猎贴。雖然這個更改在默認情況下是不可見的,但是接下來我們將向您展示您仍然需要擔心類元數據內存占用家坎。請記住嘱能,這個新特性并不能神奇地消除類和類加載器內存泄漏。您將需要使用不同的方法并通過學習新的命名約定來跟蹤這些問題虱疏。
總而言之:
PermGen空間情況
此內存空間已完全刪除惹骂。
PermSize
和MaxPermSize JVM
參數將被忽略,如果在啟動時出現做瞪,則會發(fā)出警告对粪。
元空間內存分配模型
類元數據的大多數分配現在都是從本機內存中分配的。
用于描述類元數據的klasse已被刪除装蓬。
元空間容量
默認情況下著拭,類元數據分配受可用本機內存量的限制(容量當然取決于是否使用32位JVM而不是64位以及操作系統虛擬內存可用性)。
有一個新的標志可用(MaxMetaspaceSize
)牍帚,允許您限制用于類元數據的本機內存量儡遮。如果不指定此標志,元空間將根據運行時的應用程序需求動態(tài)調整大小暗赶。
元空間垃圾回收
一旦類元數據使用量達到“MaxMetaspaceSize
”鄙币,就會觸發(fā)對死類和類加載器的垃圾回收。
顯然需要對元空間進行適當的監(jiān)視和調優(yōu)蹂随,以限制此類垃圾收集的頻率或延遲十嘿。過多的元空間垃圾收集可能是類、類加載器內存泄漏或應用程序大小不足的癥狀岳锁。
Java堆空間影響
一些雜項數據已移動到Java堆空間绩衷。這意味著您可能會在未來的jdk8升級后觀察到Java堆空間的增加。
元空間監(jiān)測
Metaspace
用法可從HotSpot 1.8詳細GC日志輸出中獲得。
根據我們對b75的測試咳燕,Jstat
和JVisualVM
還沒有更新勿决,舊的PermGen空間引用仍然存在。
理論足夠了招盲,讓我們看看這個新的內存空間是如何通過我們泄漏的Java程序運行的…
更多細節(jié)可以參考這一篇介紹:http://javakk.com/417.html
PermGen與Metaspace運行時比較
為了更好地理解新元空間內存空間的運行時行為剥险,我們創(chuàng)建了一個類元數據泄漏Java程序。你可以在這里下載源代碼宪肖。
將測試以下場景:
- 使用jdk1.7運行Java程序,以監(jiān)視并耗盡設置為128mb的PermGen內存空間健爬。
- 使用jdk1.8(b75)運行Java程序控乾,以監(jiān)視新
Metaspace
內存空間的動態(tài)增加和垃圾收集。 - 使用jdk1.8(b75)運行Java程序娜遵,通過將
MaxMetaspaceSize
值設置為128mb來模擬元空間的消耗
JDK 1.7@64位-永久代消耗
- 具有50K配置迭代的Java程序
- 1024 MB的Java堆空間
- Java PermGen空間為128 MB(
-XX:MaxPermSize=128m
)
正如您在JVisualVM中看到的蜕衡,PermGen耗盡是在加載了大約30K+個類之后達到的。我們也可以從程序和GC輸出中看到這種消耗设拟。
Class metadata leak simulator
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com
ERROR: java.lang.OutOfMemoryError: PermGen space
現在讓我們使用hotspotsjdk1.8jre執(zhí)行該程序慨仿。
JDK 1.8@64位–元空間動態(tài)調整大小
- 具有50K配置迭代的Java程序
- 1024 MB的Java堆空間
- Java元空間:無邊界(默認)
從詳細的GC輸出中可以看到,JVM元空間確實從20mb動態(tài)擴展到328mb的保留本機內存纳胧,以滿足Java程序增加的類元數據內存占用镰吆。我們還可以觀察到JVM試圖銷毀任何死類或類加載器對象時的垃圾收集事件。由于我們的Java程序正在泄漏跑慕,JVM別無選擇万皿,只能動態(tài)擴展元空間內存空間。該程序能夠在沒有OOM事件的情況下運行其50K次迭代核行,并加載了50K+個類牢硅。讓我們轉到最后一個測試場景。
JDK 1.8@64位-元空間耗盡
- 具有50K配置迭代的Java程序
- 1024 MB的Java堆空間
- Java元空間:128 MB(
-XX:MaxMetaspaceSize=128m
)
正如您在JVisualVM中看到的芝雪,元空間耗盡是在加載了大約30K+個類之后達到的减余;這與jdk1.7的運行非常相似。我們也可以從程序和GC輸出中看到這一點惩系。另一個有趣的觀察是位岔,保留的本機內存占用是指定的最大大小的兩倍。這可能表明有機會微調Metaspace resize
策略(如果可能)蛆挫,以避免本機內存浪費赃承。
現在在下面找到我們從Java程序輸出中得到的異常。
Class metadata leak simulator
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com
ERROR: java.lang.OutOfMemoryError: Metadata space
正如預期的那樣悴侵,將元空間限制在128MB瞧剖,就像我們在JDK1.7的基線運行中所做的那樣,不允許我們完成程序的50K迭代。JVM拋出了一個新的OOM錯誤抓于。上面的OOM事件是JVM在內存分配失敗后從元空間拋出的
當前的觀察結果明確表明做粤,為了避免諸如上一個測試場景觸發(fā)的過多的元空間GC或OOM條件等問題,需要進行適當的監(jiān)控和調優(yōu)捉撮。以后的文章可能會包括性能比較怕品,以確定與此新特性相關的潛在性能改進。
文章來源:http://javakk.com/421.html
也歡迎大家關注我的公眾號【Java老K】獲取更多干貨