解码Java.Lang.OutOfMemoryError:PermGen空间
Java開發(fā)人員最不了解的領(lǐng)域之一是垃圾收集。 Java開發(fā)人員認(rèn)為JVM負(fù)責(zé)垃圾收集,因此他們不必?fù)?dān)心內(nèi)存分配,釋放等問題。但是,隨著應(yīng)用程序變得越來越復(fù)雜,垃圾收集也會變得越來越復(fù)雜,一旦性能變得復(fù)雜,性能便會受到影響。 因此,這將有利于Java開發(fā)人員了解垃圾回收的工作原理以及如何解決Java中的“內(nèi)存不足”問題。 有2個非常常見的“內(nèi)存不足”問題。 第一個是“堆大小”,第二個是“ PermGen空間”。
永久生成器和ClassLoader。
Java對象是Java類的實例。 每次創(chuàng)建新的Java對象時,JVM都會創(chuàng)建該對象的內(nèi)部表示并將其存儲在堆中。 如果是第一次訪問該類,則必須由JVM加載它。 類加載是以下過程:查找相應(yīng)的類文件,在磁盤上查找文件,加載文件并解析結(jié)構(gòu)。 確保正確加載類是ClassLoaders的責(zé)任。java程序中的每個類都需要由同一ClassLoader加載。 ClassLoader是java.lang.ClassLoader類的實例。 現(xiàn)在,ClassLoader將Java類加載到Perm Space中。
JVM還創(chuàng)建了Java類的內(nèi)部表示,這些類存儲在永久代中。 在垃圾回收期間,java對象和類都被視為對象,并且以相同的方式進(jìn)行垃圾回收。 最初,java對象和類都存儲在堆空間中。
為了優(yōu)化性能,創(chuàng)建了永久代,并在其中放置了類。類是我們JVM實現(xiàn)的一部分,我們不應(yīng)該用數(shù)據(jù)結(jié)構(gòu)填充Java堆。 永久代分配在堆大小之外。 永久世代包含以下類信息:
- 一類的方法。
- 類的名稱。
- 常量池信息。
- 與類關(guān)聯(lián)的對象數(shù)組和類型數(shù)組。
- JVM使用的內(nèi)部對象。
- 編譯器用于優(yōu)化的信息。
現(xiàn)在我們了解了什么是永久生成,讓我們看看是什么導(dǎo)致該區(qū)域的內(nèi)存問題。
PermGen空間
當(dāng)JVM需要加載新類的定義并且PermGen中沒有足夠的空間時,會發(fā)生“ Java.Lang.OutOfMemoryError:PermGen空間”。 服務(wù)器模式分配的默認(rèn)PermGen空間為64 MB,客戶端模式分配的默認(rèn)為32 MB。 發(fā)生PermGen Space問題的原因可能有兩個。
第一個原因可能是您的應(yīng)用程序或服務(wù)器中的類太多,而現(xiàn)有的PermGen Space無法容納所有類。
-XX:MaxPermSize = XXXM
如果問題是由于類數(shù)量過多而導(dǎo)致PermGen空間不足,則可以通過添加–XX:MaxPermSize = XXm參數(shù)來增加PermGen空間。 這將增加可用于存儲類的空間,并且應(yīng)-XX:MaxPermSize = 256m
-XX:+ CMSClassUnloadingEnabled
此參數(shù)指示使用CMS GC時是否啟用類卸載。 默認(rèn)情況下,此選項設(shè)置為false,因此要啟用此功能,您需要在java options中顯式設(shè)置以下選項。
-XX:+ CMSClassUnloadingEnabled
如果啟用CMSClassUnloadingEnabled,則GC也會清除PermGen,并刪除不再使用的類。僅當(dāng)使用以下選項啟用UseConcMarkSweepGC時,此選項才有效。
-XX:+ UseConcMarkSweepGC
-XX:+ CMSPermGenSweepingEnabled
此參數(shù)指示是否啟用了掃描電燙。 默認(rèn)情況下,此參數(shù)是禁用的,因此需要顯式設(shè)置此參數(shù)以微調(diào)PermGen問題。 在Java 6中已刪除此選項,因此,如果使用Java 6或更高版本,則需要使用-XX:+ CMSClassUnloadingEnabled。 因此,為解決PermGen Space內(nèi)存問題而添加的選項如下所示
-XX:MaxPermSize = 128m -XX:+ UseConcMarkSweepGC XX:+ CMSClassUnloadingEnabled
內(nèi)存泄漏
第二個原因可能是內(nèi)存泄漏。 裝入的類定義可能如何變得未使用。
通常在Java中,類是永遠(yuǎn)的。 因此,一旦加載了類,即使該應(yīng)用程序在服務(wù)器上停止,它們也會保留在內(nèi)存中。 像cglib這樣的動態(tài)類生成庫使用了許多PermGen Space,因為它們動態(tài)創(chuàng)建了很多類。 大量使用Proxy類,這些類是在運行時綜合創(chuàng)建的。 當(dāng)單個類定義可用于多個實例時,創(chuàng)建新的代理類很容易。
Spring和Hibernate通常代理某些類。 此類代理類由類加載器加載。 永遠(yuǎn)不會丟棄生成的類定義,從而導(dǎo)致永久堆空間快速填充。
對于PermGen空間問題,您將需要確定泄漏原因并加以解決。 增加PermGen空間將無濟(jì)于事,只會延遲問題,因為在某些時候PermGen空間仍會被填滿。
如果您使用的是Tomcat并因內(nèi)存泄漏而困擾,那么最新版本的Tomcat可以修復(fù)某些內(nèi)存泄漏問題。
- http://wiki.apache.org/tomcat/MemoryLeakProtection
結(jié)論
一旦遇到PermGen Space問題,您將需要找出問題是由于您的應(yīng)用程序正在加載大量類還是由于內(nèi)存泄漏引起的。 如果是由于類數(shù)量過多,您可以進(jìn)行微調(diào)以增加分配的PermGen空間,這將解決此問題。 如果問題是由于內(nèi)存泄漏引起的,則需要找到泄漏的根本原因并加以解決。 某些框架的工作方式如cglib,Spring,Hibernate會創(chuàng)建大量動態(tài)生成的類,因此最好使用這些框架為項目分配更多的PermGen Space。
翻譯自: https://www.javacodegeeks.com/2013/12/decoding-java-lang-outofmemoryerror-permgen-space.html
總結(jié)
以上是生活随笔為你收集整理的解码Java.Lang.OutOfMemoryError:PermGen空间的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 超星安卓版(超星安卓)
- 下一篇: 想要更快地使用AtomicLong? 等