除了一些非常模糊的高級定義,例如「擺脫PermGen問題」(which it doesn't,btw)之外,我不能在我的生活中找到Java VM標誌CMSClassUnloadingEnabled
實際所做的定義。JVM標誌CMSClassUnloadingEnabled實際上做了什麼?
我看了Sun的/ Oracle的網站,甚至the options list也沒有說明它的功能。
根據國旗的名稱,我猜CMS的垃圾收集器不會默認地卸載類,並且這個標誌將它打開 - 但我不能確定。
除了一些非常模糊的高級定義,例如「擺脫PermGen問題」(which it doesn't,btw)之外,我不能在我的生活中找到Java VM標誌CMSClassUnloadingEnabled
實際所做的定義。JVM標誌CMSClassUnloadingEnabled實際上做了什麼?
我看了Sun的/ Oracle的網站,甚至the options list也沒有說明它的功能。
根據國旗的名稱,我猜CMS的垃圾收集器不會默認地卸載類,並且這個標誌將它打開 - 但我不能確定。
更新這個答案是相關的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
根據博客文章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時發生的情況。 (或者至少,如果可以避免導致存儲泄漏泄漏的問題,那麼應該會發生這種情況。)
一個例子,這是有用的:
我們的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反射和代理的時候非常有用據http://stackoverflow.com/a/3720052/2541爲'CMSClassUnloadingEnabled'有任何影響,UseConcMarkSweepGC必須也設置 – 2012-08-15 16:05:50
不知道這是如何影響使用UseConcatSweepGC的想法,但它似乎有一個最近在CMSClassUnloadingEnabled中修復的錯誤。這裏指出這是固定的:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8000325 – BillR 2013-06-10 02:51:17
對於像Groovy這樣的動態定義類的語言,啓用此標誌是否定期清除PermGen是一種好習慣? – 2013-08-17 19:58:18