Java 常見的幾種內(nèi)存溢出異常的原因及解決
內(nèi)存溢出的異常有很多,并且每種內(nèi)存溢出都會有不同的異常信息和解決方式,下面會列出常見的幾種內(nèi)存溢出異常
堆內(nèi)存溢出java.lang.OutOfMemoryError: Java heap space
原因: 當(dāng)堆內(nèi)存不足,并且已經(jīng)達(dá)到JVM設(shè)置的最大值,無法繼續(xù)申請新的內(nèi)存,存活的對象在堆內(nèi)存中無法被回收,那么就會拋出該異常,表示堆內(nèi)存溢出。 當(dāng)一次從數(shù)據(jù)庫查詢大量數(shù)據(jù),堆內(nèi)存沒有足夠的內(nèi)存可以存放大量的數(shù)據(jù) 大量的強引用對象在堆內(nèi)存中存活,GC無法回收這些對象,新創(chuàng)建的對象在新生代無法進(jìn)行分配,F(xiàn)ull GC仍然無法進(jìn)行回收解決方案: 查看當(dāng)前JVM的堆內(nèi)存配置是否太小,可以考慮增加堆內(nèi)存大小JAVA_OPTS='-server -Xms1024m -Xmx1024m'
表示將堆內(nèi)存的初始值和最大值都設(shè)置為1024m
-Xms設(shè)置堆內(nèi)存的初始值
-Xmx設(shè)置堆內(nèi)存的最大值
-Xms和-Xmx最好設(shè)置相同的內(nèi)存大小,可以防止因為JVM頻繁進(jìn)行內(nèi)存的調(diào)整影響穩(wěn)定性和使用
查看代碼中是否有從數(shù)據(jù)庫中一次加載大量數(shù)據(jù)的情況,或者代碼中有大量強引用無法進(jìn)行回收通過JVM參數(shù):-XX:+HeapDumpOnOutOfMemoryError可以讓虛擬機(jī)在出現(xiàn)內(nèi)存溢出的時候Dump出當(dāng)前的堆內(nèi)存快照,便于保留快照分析
棧內(nèi)存溢出java.lang.outOfMemoryError:StackOverFlow Error
原因: 線程請求的棧深度大于虛擬機(jī)允許的最大深度,拋出StackOverflowError 虛擬機(jī)在擴(kuò)展棧時無法申請到足夠的內(nèi)存空間,拋出OutOfMemoryError 解決方案: 檢查代碼是否出現(xiàn)深度遞歸的情況,或者遞歸的終止條件沒有設(shè)置 如果是線程的棧內(nèi)存空間過小,則通過-Xss設(shè)置每個線程的棧內(nèi)存空間默認(rèn)的-Xss參數(shù)的大小應(yīng)該是1M
棧內(nèi)存是線程私有的,如果需要創(chuàng)建更多的線程,那么就需要將每個線程的棧內(nèi)存空間減小,通過-Xss參數(shù)設(shè)置每個線程的棧內(nèi)存空間
配置參數(shù): JAVA_OPTS='-server -Xms1024m -Xmx1024m -Xss128k'
jdk8如果沒有配置-Xss默認(rèn)大小為512k
-Xss 設(shè)置每個線程的堆棧大小,一般默認(rèn)512~1024kb,和jdk版本有關(guān)
方法區(qū)和運行時常量池內(nèi)存溢出java.lang.outOfMemoryError: PermGen space
原因: 方法區(qū)存放的是Class的相關(guān)信息,如類名、訪問修飾符、常量池、字段描述、方法描述等,內(nèi)存溢出的原因可能是加載的類過多導(dǎo)致方法區(qū)沒有足夠的內(nèi)存 如果程序中大量使用cglib或者動態(tài)代理等對目標(biāo)類進(jìn)行代理,那么在運行時會生成大量的代理類,如Spring、Hibernate等框架。所以生成的代理類過多導(dǎo)致方法區(qū)沒有足夠的內(nèi)存解決方案:
減少沒有必要的Class加載,防止方法區(qū)內(nèi)存溢出并且減少程序的編譯時間 通過JVM參數(shù)設(shè)置方法區(qū)的大小,-XX:PermSize和-XX:MaxPermSize設(shè)置方法區(qū)的大小運行時常量池是方法區(qū)的一部分,所以增加方法區(qū)的內(nèi)存大小,相當(dāng)于間接的增加了運行時常量池的內(nèi)存大小
本機(jī)直接內(nèi)存溢出Direct buffer memory
Java 允許應(yīng)用程序通過 DirectByteBuffer 直接訪問堆外內(nèi)存,許多高性能程序通過 DirectByteBuffer 結(jié)合內(nèi)存映射文件(Memory Mapped File)實現(xiàn)高速 IO
原因:DirectByteBuffer 的默認(rèn)大小為 64 MB,一旦使用超出限制,就會拋出 Direct buffer memory 錯誤。使用NIO則可能會出現(xiàn)該異常
解決方案:DirectMemory的內(nèi)存大小可以通過-XX:MaxDirectMemorySize指定,如果沒有設(shè)置,則默認(rèn)和Java堆最大值(-Xmx)一樣
元空間內(nèi)存溢出Metaspace
Jdk8 之后使用元空間(metaspace)代替永久代,元空間和永久代最大的區(qū)別是元空間的內(nèi)存使用的是本地內(nèi)存,而永久代使用的是JVM的內(nèi)存
永久代、元空間都是方法區(qū)的實現(xiàn),方法區(qū)是規(guī)范
原因:元空間中存儲的是類信息、常量池、方法描述等信息,直接使用本地內(nèi)存,當(dāng)本地內(nèi)存不足的時候,會拋出OutOfMemoryError:Metaspace異常
解決方案:雖然元空間的內(nèi)存不是由JVM控制,不過可以通過JVM參數(shù)來設(shè)置分配的內(nèi)存空間的大小-XX:MaxMetaspaceSize配置參數(shù)
以上就是Java 常見的幾種內(nèi)存溢出異常及解決的詳細(xì)內(nèi)容,更多關(guān)于Java 內(nèi)存溢出的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
