簡體   English   中英

元空間增長、死類加載器和 GC

[英]Metaspace growth, dead classloader and GC

我們遇到這樣一種情況,其中 springboot 微服務的元空間不斷增長,但堆運行良好。

jmap -clstats 顯示有大量以下類型的死類加載器。

0x00000000e3c8e3c8 1 4087 0x00000000e0004d18死 com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl$TransletClassLoader@0x000000010087c7e8

在最初的高水位線 GC 被觸發,我看到元空間下降。 在由於定義的元空間大小而觸發的強制 GC 之后,我看到元空間不斷增長,並且我看到更多相同類型的死類加載器保留在元空間中。 我確實看到了一些 GC 活動,但元空間消耗沒有下降。 但是,如果我通過 visualvm 強制 GC 收集,大量類將被卸載,元空間消耗將返回到服務啟動時的 state。

為什么 JVM 托管 GC 不會卸載這些死掉的類加載器,而強制 GC 會卸載這些加載器? 如果弱/軟/幻象引用是原因,那么它不應該也適用於強制 GC 嗎?

這是在 Java8 上。 任何人都可以就我接下來應該看的地方給出一些指示嗎? 顯然存在泄漏,那么有沒有辦法知道 TemplatesImpl$TransletClassLoader 的父類加載器?

感謝任何幫助。

首先,JVM 只會在 Full GC 期間清除 Metaspace,而不會在 Young GC 期間清除。 所以你看到的行為是意料之中的。

在最初的高水位線 GC 被觸發,我看到元空間下降。

如果您檢查 GC 跟蹤,您將看到一個 System.GC() 調用。 那就是 Full GC。

但是,如果我通過 visualvm 強制 GC 收集,大量類將被卸載,元空間消耗將返回到服務啟動時的 state。

同樣,這將是一次由 visualvm 觸發的 Full GC,可以在 GC trace 中看到。 這就是您看到利用率下降的原因。

根據您提供的描述,我認為您沒有類加載器泄漏,因為所有內容都在 Full GC 期間被清理。 根據我的經驗,如果應用程序不必要地使某些對象保持活動狀態,因此不會被垃圾收集,我只會將其視為“內存泄漏”——即使在 Full GC 期間也是如此。 在您的情況下,我建議使用-XX:MaxMetaspaceSize標志來限制元空間大小。 當占用率達到該閾值時,JVM 將自動觸發 Full GC,正如您所注意到的,元空間的使用率將下降。 明智地設置該限制,因為太低的值會導致java.lang.OutOfMemoryError: Metaspace問題。

可以在此處找到有關元空間的更多詳細信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM