2010-07-26 19 views
168

除了一些非常模糊的高級定義,例如「擺脫PermGen問題」(which it doesn't,btw)之外,我不能在我的生活中找到Java VM標誌CMSClassUnloadingEnabled實際所做的定義。JVM標誌CMSClassUnloadingEnabled實際上做了什麼?

我看了Sun的/ Oracle的網站,甚至the options list也沒有說明它的功能。

根據國旗的名稱,我猜CMS的垃圾收集器不會默認地卸載類,並且這個標誌將它打開 - 但我不能確定。

回答

201

更新這個答案是相關的Java 5-7,爪哇8有這個固定的:https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace榮譽去mt.uulu

對於Java 5-7:

標準的甲骨文/ Sun VM旁觀世界是:類是永遠的。所以一旦加載,即使沒有人在意,他們也會留在記憶中。這通常是沒有問題的,因爲你沒有那麼多純粹的「設置」類(=一次用於設置,然後再也不用)。所以即使他們佔用1MB,誰在乎。但最近,我們有像Groovy這樣的語言,它定義了運行時的類。每次運行腳本時,都會創建一個(或多個)新類,並永久保留在PermGen中。如果您運行的是服務器,那意味着您有內存泄漏。

如果啓用CMSClassUnloadingEnabled,GC也會掃描PermGen,並刪除不再使用的類。

[編輯]您還必須啓用UseConcMarkSweepGC(感謝Sam Hasler)。看到這個答案:https://stackoverflow.com/a/3720052/2541

+15

是大量使用Java反射和代理的時候非常有用據http://stackoverflow.com/a/372​​0052/2541爲'CMSClassUnloadingEnabled'有任何影響,UseConcMarkSweepGC必須也設置 – 2012-08-15 16:05:50

+1

不知道這是如何影響使用UseConcatSweepGC的想法,但它似乎有一個最近在CMSClassUnloadingEnabled中修復的錯誤。這裏指出這是固定的:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8000325 – BillR 2013-06-10 02:51:17

+0

對於像Groovy這樣的動態定義類的語言,啓用此標誌是否定期清除PermGen是一種好習慣? – 2013-08-17 19:58:18

34

根據博客文章The most complete list of -XX options for Java JVM,它確定是否在CMS垃圾收集器下啓用類卸載。默認值是false。還有另一個選項ClassUnloading,默認爲true(推測)會影響其他垃圾收集器。

這個想法是,如果GC檢測到以前加載的類不再在JVM中的任何位置使用,它可以回收用於存放類字節碼和/或本機代碼的內存。如果你正在使用CMS收集

設置CMSClassUnloadingEnabled 可能幫助您PermGen的問題。但有可能你沒有使用CMS,或者你有一個真正的類加載器相關的內存泄漏。在後一種情況下,你的班級永遠不會顯示給GC未使用......因此永遠不會被卸載。


Aaron Digulla說「班級永遠」。即使在純粹的Java世界中,這也不是完全正確的。實際上,一個類的生命週期與其類加載器相關聯。所以如果你能夠安排一個類加載器被垃圾收集(這並不總是一件容易的事情),它所加載的類也將被垃圾收集。

實際上,這是當您重新部署webapp時發生的情況。 (或者至少,如果可以避免導致存儲泄漏泄漏的問題,那麼應該會發生這種情況。)

22

一個例子,這是有用的:

我們的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

+0

+1分享真實體驗。我們在扭矩箱上也遇到了這個問題,由於JRuby編譯過程,服務器產生了大量的類。 – nurettin 2013-03-22 07:42:29

+7

還注意到'-XX:+ CMSPermGenSweepingEnabled'已被棄用,以支持'-XX:+ CMSClassUnloadingEnabled' – nurettin 2013-03-22 07:53:11

+0

@nurettin:很高興知道,感謝信息 – 2013-03-22 09:14:53

相關問題