在我的最新文章中,我解釋了可能導致java.lang.OutOfMemoryError:PermGen空間崩潰的原因 。 現在該討論該問題的可能解決方案了。 或者,更確切地說,是關于互聯網對可能解決方案的建議。 不幸的是,我只能說,我對MythBusters的內心Jamie Hyneman進行了不同的“專家意見”喚醒。
我搜索了有關解決java.lang.OutOfMemoryError:PermGen空間崩潰的方法的當前常識,并瀏覽了幾十個頁面,這些頁面似乎更適合Google結果。 幸運的是,大多數建議已被提煉為備受推崇的StackOverflow的主題 。 如您所見,該主題非常受歡迎,并獲得了一些頗受好評的答案。 但是具有諷刺意味的是,整個主題包含的零解決方案我可以向我推薦。 好吧,除了“查找內存泄漏的原因”外,這當然是絕對正確的,但對回答“如何解決內存泄漏”的問題不是很有幫助。 讓我們回顧一下SO頁面上提出的建議。
使用-XX:MaxPermSize = XXXM
導致java.lang.OutOfMemoryError的原因有兩個:PermGen空間錯誤。
一種是應用程序服務器和/或應用程序確實確實使用了太多的類,以致它們不適合默認大小的永久代。 絕對有可能,但實際上并非如此。 在這種情況下,增加永久代的大小確實可以節省一天。 如果您唯一的問題是如何在太多的小房子里放太多家具,那就買更大的房子!
但是,如果您的愛心媽媽每周都會給您寄去新家具呢? 您可能無法一遍又一遍地搬到更大的房子。 正如我在上面提到的上一篇文章中所描述的,這正是內存泄漏以及類加載器泄漏的情況。 在此讓我清楚:永久代大小的增加不會使您免于類加載器泄漏。 它只能推遲。 并更難預測服務器將淘汰多少次重新部署。
-XX:+ CMSPermGenSweepingEnabled
關于StackOverflow的最流行的答案是將這些選項添加到服務器的命令行中。 而且,他們說:“也可以添加-XX:+ UseConcMarkSweepGC。 只是要確定”。 這些JVM標志的第一個問題是沒有關于它們真正作用的解釋。 無論是在SO答案中(我都不喜歡告訴您在沒有理由的情況下要做某事的答案),還是在整個Internet中都是如此。
確實,除了此頁面之外,我找不到有關這些選項的任何文檔。 但是,實際上,這甚至沒有關系。 絕不會對垃圾收集器選項進行任何修補,以防在班機泄漏時發生。 因為按照定義, 內存泄漏是GC不足的情況。 如果從服務器的類加載器中的某個地方到應用程序的對象或類之間存在有效的實時硬引用,則GC將永遠不會將其視為垃圾,也永遠不會對其進行回收。 當然,所有這些JVM標志看起來都很聰明和神奇。 在某些情況下,可能確實需要使用它們。 但是它們肯定不夠 ,不能解決您的永久代泄漏。
使用JRockit
下一個建議是切換到JRockit JVM。 理由是,由于JRockit沒有永久代,因此無法用完它。 當然,這是一個有趣的主張。 不幸的是,它也不能解決我們的問題。
此“解決方案”的唯一結果將是獲取java.lang.OutOfMemoryError:Java堆空間,而不是java.lang.OutOfMemoryError:PermGen空間。 在沒有單獨生成類定義的情況下,JRockit為它們使用通常的Java堆空間。 而且,只要泄漏的根本原因沒有得到解決,只要有足夠的時間,這些類定義甚至可以填滿最大的堆。
重新啟動服務器
假裝問題已解決的另一種方法是不時重新啟動應用程序服務器。 例如,無需重新部署應用程序,只需重新啟動整個服務器即可。 但是,當您第一次看到部署了多個應用程序的應用程序服務器時,您會知道在生產環境中幾乎不可能做到這一點。 這并不是真正的解決方案。 這是將您的頭藏在沙子里的一種方法。
使用Tomcat
實際上,這并不是以前的絕望之作-最近的Tomcat版本確實嘗試解決類加載器泄漏。 自己看看他們的文檔 。 如果您可以將Tomcat用作目標服務器,并且如果您的泄漏是Tomcat可以成功應對的泄漏之一,那么也許,也許您很幸運,問題就為您解決了。
在此處使用<您最喜歡的探查器工具>
也可能是可行的解決方案。 但是,再加上幾個IF 。 首先,您應該能夠在受影響的環境中使用該探查器。 正如我之前在其他文章中提到的那樣, 探查器施加的開銷水平在(生產)環境中可能是不可接受的。 其次,您必須知道如何使用探查器提取所需的信息并確定泄漏的位置。 而我10多年的經驗表明,這種情況很少發生。
結論
到目前為止,我們還沒有看到java.lang.OutOfMemoryError:PermGen空間錯誤的任何確定解決方案。 在某些情況下,有些方法是可行的。 但是,令我震驚的是,大多數建議都完全無效 ! 您可能會浪費數天或數周的時間來嘗試它們,甚至沒有開始解決真正的問題:找到流氓的根本原因,以防泄漏!
幸運的是,從1.1版本開始, Plumbr還發現了PermGen泄漏 。 它告訴您阻止類加載器被釋放的根本原因,從而節省了尋找漏洞的時間。 因此,下一次,當遇到java.lang.OutOfMemoryError:PermGen空間消息時, 下載Plumbr并永久擺脫該問題。
參考: Plumbr博客博客上來自我們JCG合作伙伴 Nikita Salnikov Tarnovski的 PermGen神話 。
翻譯自: https://www.javacodegeeks.com/2012/12/busting-permgen-myths.html