JAVA OOM總結


  首先,JVM除了程序計數器之外,都可能發生內存溢出OutOfMemoryError(OOM)異常。這里主要對可能發生內存溢出的區域,原因進行總結。

1.JAVA虛擬機棧

  虛擬機棧是線程私有的,虛擬機棧主要存儲局部變量。Java虛擬機規范中,規定了此區域會拋出兩種異常:

(1)如果請求棧深度大於虛擬機允許的深度,即涉及到方法層級調用太多,超過一定限度,將拋出StackOverflowError異常;這里說的棧的深度主要是java啟動參數中xss參數,虛擬機棧大小配置;

(2)虛擬機棧動態擴展,如果得不到足夠的內存申請空間,就會拋出OOM異常;虛擬機棧動態擴展,即當棧空間不夠的時候,會自動加大棧的空間,避免StackOverflowError,此時申請空間不足,便會OOM,部分虛擬機具備這個功能;

2.本地方法棧

  本地方法棧是為Native方法方法服務的,與虛擬機棧一樣,本地方法棧也會拋出OOM以及StackOverflowError異常;

3.JAVA堆

  JAVA堆是內存管理最大的一塊,是所有線程共享的一塊區域,在虛擬機啟動的時候創建,主要存儲對象實例。這塊主要通過啟動參數-Xmx進行配置,如果申請的對象實例大小超過該配置的參數,便出現OOM異常。內存泄漏也會導致該區域的OOM,內存泄漏會導致不能回收的對象停留在堆中,隨着時間推移便會消耗完堆空間出發OOM。

4.方法區

  方法區和java堆一樣,是各個線程共享的內存區域,用於存儲已被虛擬機加載的類信息,常量、靜態變量和即時編譯器編譯后的代碼數據。當方法區無法滿足內存分配,將拋出OOM異常。

  當前的一些框架,如Spring、Hibernate等,會使用CGlib技術對類進行增強,相應地會增加類的大小;
  還有一些應用,會動態生成JSP文件,JSP文件是需要編譯成Class文件的,大量的文件也有溢出的可能;
  或者開發代碼中往常量池添加過多的常量,也有可能造成常量池溢出。
  另外一種可能就是我們的應用本身的類就太多,而方法區設置的容量不足,也會容易溢出。
  設置方法區的大小,可通過配置-XX:PremSize 設置最小值,-XX:MaxPremSize設置最大值。
5.直接內存

  直接內存(Direct Memory)又稱堆外內存,內存對象分配在Java虛擬機的堆以外的內存,這些內存直接受操作系統管理(而不是虛擬機);

  (1)減少了垃圾回收

  使用堆外內存的話,堆外內存是直接受操作系統管理( 而不是虛擬機 )。這樣做的結果就是能保持一個較小的堆內內存,以減少垃圾收集對應用的影響。

  (2)提升復制速度(io效率)

  堆內內存由JVM管理,屬於“用戶態”;而堆外內存由OS管理,屬於“內核態”。如果從堆內向磁盤寫數據時,數據會被先復制到堆外內存,即內核緩沖區,然后再由OS寫入磁盤,使用堆外內存避免了這個操作。

  如果堆外內存申請超過,物理內存的限制也會出現OOM異常。

 

  

 


免責聲明!

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



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