淺談JVM內(nèi)存溢出原因和解決思路
棧溢出(虛擬機(jī)棧和本地方法棧)
產(chǎn)生原因
- 在HotSpot中,只能由-Xss參數(shù)來(lái)設(shè)定。因?yàn)樵贖otSpot中不區(qū)分虛擬機(jī)棧和本地方法棧的。
- 棧溢出時(shí)會(huì)出現(xiàn)兩種異常:StackOverflowError異常和OutOfMemoryError異常。
- StackOverflowError異常因?yàn)榫€程請(qǐng)求的棧深度大于虛擬機(jī)允許的最大深度。
- OutOfMemoryError異常發(fā)生在虛擬機(jī)棧內(nèi)存允許動(dòng)態(tài)擴(kuò)展的情況下,當(dāng)擴(kuò)展棧容量無(wú)法申請(qǐng)到足夠的內(nèi)存時(shí)。
- 因?yàn)镠otSpot是不支持?jǐn)U展的,所在除非在線程創(chuàng)建時(shí)申請(qǐng)內(nèi)存無(wú)法滿足時(shí),才會(huì)出現(xiàn)OutOfMemoryError,其余都是產(chǎn)生StackOverflowError異常。
- 結(jié)論:給每個(gè)線程的棧分配內(nèi)存不是越大越好??梢赃@么理解,比如總的內(nèi)存是2G,如果一個(gè)線程就占了1.5G,那就。。。。
解決思路
出現(xiàn) StackOverflowError異常時(shí),會(huì)有明確錯(cuò)誤堆??晒┓治?,相對(duì)而言比較容易定位到問(wèn)題所在。
如果使用Hotspot虛擬機(jī)默認(rèn)參數(shù),棧深度在大多數(shù)情況下(因?yàn)槊總€(gè)方法壓人棧的幀大小并不是一樣的,所以只能說(shuō)大多數(shù)情況下)到達(dá)1000~2000 是完全沒(méi)有問(wèn)題,對(duì)于正常的方法調(diào)用(包括不能做尾遞歸優(yōu)化的遞歸調(diào)用),這個(gè)深度應(yīng)該完全夠用了。但是,如果是建立過(guò)多線程導(dǎo)致的內(nèi)存濫出,在不能減少線程數(shù)量或者更換 64 位虛擬機(jī)的情況下,就只能通過(guò)減少最大堆和減少棧容量來(lái)?yè)Q取更多的線程。
堆溢出
產(chǎn)生原因
當(dāng)不斷的創(chuàng)建對(duì)象并避免垃圾回收時(shí),總?cè)萘坑|及最大堆容量時(shí),就會(huì)產(chǎn)生溢出。
運(yùn)行代碼:設(shè)置vm參數(shù)-Xms10m -Xmx10m
public class HeapTest { static class OOMObj{ } /** * vm arg -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError */ public static void main(String[] args) { List<OOMObj> oomObjList = new ArrayList<OOMObj>(); while (true){ oomObjList.add(new OOMObj()); } } }
結(jié)果:
解決思路
首先通過(guò)內(nèi)存映像分析工具確認(rèn)是內(nèi)存泄漏還是內(nèi)存溢出。
- 如果是內(nèi)存泄漏,說(shuō)明導(dǎo)致OOM的對(duì)象不是必要的。進(jìn)一步通過(guò)工具查看GC Roots引用鏈。一般可以比較精確的定位。
- 如果是內(nèi)存溢出,對(duì)象是必須存活的,那就檢查虛擬機(jī)的堆參數(shù)-Xms、-Xmx設(shè)置,對(duì)比機(jī)器內(nèi)存,看是否還有上調(diào)的空間。再?gòu)拇a上檢查對(duì)象生命周期、持有狀態(tài)時(shí)間、存儲(chǔ)結(jié)構(gòu)是否有設(shè)計(jì)不合理等情況。
方法區(qū)和運(yùn)行時(shí)常量池溢出
產(chǎn)生原因
一個(gè)類(lèi)要被垃圾收集器回收,條件是比較苛刻的。在經(jīng)常運(yùn)行時(shí)生成大量動(dòng)態(tài)類(lèi)的應(yīng)用場(chǎng)景里,就應(yīng)該特別關(guān)注了。
解決思路
HotSpot在JDK8中已經(jīng)完全使用元空間代替永久帶。Hotspot提供了一些參數(shù)作為元空間的防御措施,主要包括:
- XX:MaxMetaspacesize:設(shè)置元空間最大值,默認(rèn)是-1,即不限制,或者說(shuō)只受限于本地內(nèi)存大小。
- -XX:Metaspacesize :指定元空間的初始空間大小,以宇節(jié)為單位,達(dá)到該值就會(huì)觸發(fā)垃圾收集進(jìn)行類(lèi)型卸載,同時(shí)收集器會(huì)對(duì)該值進(jìn)行調(diào)整:如果釋放了大量的空間,就適當(dāng)降低該值;如果釋放了很少的空間,那么在不超過(guò)-XX:MaxMetaspaceSize(如果設(shè)置了的話)的情況下,適當(dāng)提高該值。
- -XX:MinMetaspace Free Ratio:作用是在垃圾收集之后控制最小的元空間剩余容量的百分比,可減少因?yàn)樵臻g不足導(dǎo)致的垃圾收集的頻率。類(lèi)似的還有-xx:Max-MetaspaceFreeRatio,用于控制最大的元空間剩余容量的百分比。
本機(jī)直接內(nèi)存溢出
產(chǎn)生原因
在直接或間接使用了ByteBuffer中的allocateDirect方法的時(shí)候,而不做clear的時(shí)候就會(huì)出現(xiàn)類(lèi)似的問(wèn)題。明顯的特征是在Heap Dump文件中不會(huì)看到明顯的異常情況。
解決思路
設(shè)置參數(shù): -XX:MaxDirectMemorySize
到此這篇關(guān)于淺談JVM內(nèi)存溢出原因和解決思路的文章就介紹到這了,更多相關(guān)JVM內(nèi)存溢出內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis plus 開(kāi)啟sql日志打印的方法小結(jié)
Mybatis-Plus(簡(jiǎn)稱MP)是一個(gè) Mybatis 的增強(qiáng)工具,在 Mybatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生。本文重點(diǎn)給大家介紹mybatis plus 開(kāi)啟sql日志打印的方法小結(jié),感興趣的朋友一起看看吧2021-09-09Java實(shí)現(xiàn)文件上傳的兩種方法(uploadify和Spring)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)文件上傳的兩種方法,uploadify和Spring實(shí)現(xiàn)文件上傳,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11動(dòng)態(tài)配置Spring Boot日志級(jí)別的全步驟
這篇文章主要給大家介紹了關(guān)于動(dòng)態(tài)配置Spring Boot日志級(jí)別的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04java阻塞隊(duì)列BlockingQueue詳細(xì)解讀
這篇文章主要介紹了java阻塞隊(duì)列BlockingQueue詳細(xì)解讀,在新增的Concurrent包中,BlockingQueue很好的解決了多線程中,如何高效安全“傳輸”數(shù)據(jù)的問(wèn)題,通過(guò)這些高效并且線程安全的隊(duì)列類(lèi),為我們快速搭建高質(zhì)量的多線程程序帶來(lái)極大的便利,需要的朋友可以參考下2023-10-10詳解Spring與Mybatis整合方法(基于IDEA中的Maven整合)
這篇文章主要介紹了Spring與Mybatis整合方法(基于IDEA中的Maven整合),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10struts升級(jí)到2.5.2遇到的問(wèn)題及解決方案(推薦)
原來(lái)的版本是2.3.x,由于安全原因需要升級(jí)到2.5.2。但是在升級(jí)過(guò)程中遇到各種各樣的問(wèn)題,下面小編給大家?guī)?lái)了struts升級(jí)到2.5.2遇到的問(wèn)題及解決方案,需要的朋友參考下吧2016-11-11java GUI編程之布局控制器(Layout)實(shí)例分析
這篇文章主要介紹了java GUI編程之布局控制器(Layout),結(jié)合實(shí)例形式分析了java GUI編程中布局控制器(Layout)具體功能、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2020-01-01Eclipse+Java+Swing實(shí)現(xiàn)斗地主游戲(代碼)
這篇文章主要介紹了Eclipse+Java+Swing實(shí)現(xiàn)斗地主游戲并附上詳細(xì)的代碼實(shí)現(xiàn),正在學(xué)習(xí)的你可以當(dāng)小練習(xí)練練,希望對(duì)你有所幫助2022-01-01Java實(shí)現(xiàn)二分查找BinarySearch算法
這篇文章主要介紹了Java實(shí)現(xiàn)二分查找BinarySearch算法,二分查找針對(duì)的是一個(gè)有序的數(shù)據(jù)集合,每次都通過(guò)跟區(qū)間的中間元素對(duì)比,將待查找的區(qū)間縮小為之前的一半,直到找到要查找的元素,或者區(qū)間被縮小為 0,需要的朋友可以參考下2023-12-12