[英]What does JVM flag CMSClassUnloadingEnabled actually do?
更新此答案與Java 5-7相關,Java 8已修復此問題: https: //blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace Kudos轉到mt。 uulu
對於Java 5-7:
世界上標准的Oracle / Sun VM外觀是:類是永遠的。 因此,一旦加載,即使沒有人關心,它們也會留在記憶中。 這通常沒有問題,因為你沒有那么多純粹的“設置”類(=一次用於安裝,然后再沒有用過)。 因此,即使他們占用1MB,誰也在乎。
但是最近,我們有像Groovy這樣的語言,它們在運行時定義了類。 每次運行腳本時,都會創建一個(或多個)新類,它們永遠保留在PermGen中。 如果您正在運行服務器,則意味着您有內存泄漏。
如果啟用CMSClassUnloadingEnabled
,GC也將掃描PermGen,並刪除不再使用的類。
[編輯]您還必須啟用UseConcMarkSweepGC
(感謝Sam Hasler )。 請參閱此答案: https : //stackoverflow.com/a/3720052/2541
根據博客文章Java JVM的最完整的-XX選項列表 ,它確定是否在CMS垃圾收集器下啟用了類卸載。 默認值為false
。 還有另一個名為ClassUnloading
選項,默認情況下為true
(可能)會影響其他垃圾收集器。
這個想法是,如果GC檢測到JVM中的任何地方不再使用先前加載的類,它可以回收用於保存類字節碼和/或本機代碼的內存。
如果您當前正在使用CMS收集器,則設置CMSClassUnloadingEnabled 可能有助於解決您的permgen問題。 但是你可能沒有使用CMS,或者你有一個真正的類加載器相關的內存泄漏。 在后一種情況下,您的類將永遠不會在GC中顯示為未使用...因此永遠不會卸載。
Aaron Digulla說“課程永遠都是”。 即使在純Java世界中,這也不是嚴格意義上的。 實際上,類的生命周期與其類加載器相關聯。 因此,如果你可以安排一個類加載器被垃圾收集(這並不總是一件容易的事),它加載的類也將被垃圾收集。
實際上,當您對Web應用進行熱重新部署時會發生這種情況。 (或者至少,如果你能避免導致permgen存儲泄漏的問題,那就應該發生什么。)
這個例子很有用:
在我們的Weblogic 10.3 JVM上設置-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled
幫助解決了JAX-WS實現為每個Web服務調用創建新代理類的問題,最終導致內存不足錯誤。
追蹤並非易事。 以下代碼始終返回port
的相同代理類
final MyPortType port =
Service.create(
getClass().getResource("/path/to.wsdl"),
new QName("http://www.example.com", "MyService"))
.getPort(
new QName("http://www.example.com", "MyPortType"),
MyPortType.class);
在內部,此代理委托給weblogic.wsee.jaxws.spi.ClientInstance
的實例,該實例再次委托給新的$Proxy[nnnn]
類,其中n
在每次調用時遞增。 添加標志時, n
仍然會增加,但至少從內存中刪除了這些臨時類。
更一般地說,當通過java.lang.reflect.Proxy
大量使用Java反射和代理時,這非常有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.