OOM問題定位


    一:堆內存溢出

    Java創建的對象一般都是分配在堆中,如果是由於過期對象沒能回收(內存泄漏)或者對象過多導致放不下(內存溢出),一般報錯:

    Exception in thread \"main\" java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:2760)
        at java.util.Arrays.copyOf(Arrays.java:2734)
        at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
        at java.util.ArrayList.add(ArrayList.java:351)
        at test.java.VM.OOM.HeapOOM.main(HeapOOM.java:19)

     解決這部分的異常,重點是通過內存映像分析工具分析堆的轉儲快照,確定異常是由於內存泄漏還是內存溢出導致的。

     如果是內存泄漏導致的,則進一步查看泄漏對象到GCRoots的引用鏈,觀察泄漏對象是通過怎樣的路徑與GCRoots相關聯並導致垃圾回收器無法回收的;

     如果是內存溢出導致的,則檢測堆的大小參數(Xmx、Xms)看看能否再調大,檢測是否有某些對象生命周期過長。

 

    二:方法區溢出

    方法區主要存放類的信息、靜態變量、常量池等,當常量池溢出或者不停地有類動態創建並加載時,方法區也能產生OOM。

    報錯信息:

Exception in thread \"main\" java.lang.OutOfMemoryError: PermGen space

      拓展:String.intern():如果字符串常量池已經包含一個等於此string對象的字符串,則返回該字符串;否則,將次string對象的內容加入到常量池中,並返回該對象的引用。

 

   三:棧溢出(虛擬機棧、本地方法棧)

   棧的異常有兩種:

   JVM在執行方法時就會創建方法棧,方法的遞歸、調用等使得其他方法不停地入棧,其他方法執行完畢就會彈出棧幀。當一個方法棧的深度大於JVM所允許的深度時就會報StackOverFlow;一般,出現StackOverFlow時就要檢查代碼是否有無窮遞歸的情況出現了。

    stack length:1007Exception in thread \"main\" java.lang.StackOverflowError

        at test.java.VM.OOM.JavaVMStackOF.stackLeak(JavaVMStackOF.java:13)
        at test.java.VM.OOM.JavaVMStackOF.stackLeak(JavaVMStackOF.java:14)

   棧空間擴展時沒有足夠的內存則報OutOfMemory。

 

   四:本地直接內存溢出

   直接內存可以通過 -XX:MaxDirectMemorySize指定。如果本地直接內存溢出,我們可以發現堆轉儲快照中無明顯異常指示,並且快照文件很小,而程序中又使用了NIO等技術,則可以檢查是否直接內存溢出了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM