天天看點

OOM三種類型

OOM的三種類型:

堆OOM

/**
     * -Xmx1g -XX:+PrintGCDetails -XX:MaxDirectMemorySize=100m
     *
     * @param args
     */
    public static void main(String[] args) { ArrayList<byte[]> arrayList = new ArrayList<>(); for (int i = 
           

運作結果:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at com.Test.main(Test.java:15)

解決方法: 增大Xmx值 使用MAT,JProfile等工具進行代碼分析與優化

直接記憶體OOM

/**
     * -Xmx1g -XX:+PrintGCDetails -XX:MaxDirectMemorySize=100m
     * @param args
     */
    public static void main(String[] args) { for (int i = 
           

運作結果: 

直接記憶體設定為2M,超過100M時,進行回收

解決方法: 增大MaxDirectMemorySize的值

過多線程導緻的OOM

/**
     * -Xmx1g -XX:+PrintGCDetails 
     -XX:MaxDirectMemorySize=100m
     -Xss:指定棧空間大小
     *
     * @param args
     */
    public static void main(String[] args) { for (int i = 
           

運作結果: 

OOM unable to create native thread

解決方法: 減少線程數、或減少堆空間與線程空間

永久(Pern)溢出

永久區是存儲類中繼資料的區域

/**
     * -Xmx1g -XX:+PrintGCDetails 
     *
     * @param args
     */
    public static void main(String[] args) { for (int i = 
           

運作結果: 

OOM Permgen sace

 解決方法:

  • 增大MaxPremSize的值
  • 減少系統需要的類的數量
  • 使用ClassLoader合理裝載類,并進行回收

GC效率低下引起的OOM

判斷GC引起OOM的條件

  1. 花在GC上的時間是否超過了98%
  2. 老年代釋放的記憶體是否小于2%
  3. Eden區釋放的記憶體是否小于2%
  4. 是否連續5次GC都出現了上述幾種情況

關閉OOM可以通過參數:-XX:-UseGCOverheadLimit 進行設定

String常量池因其的OOM

/**
     * -Xmx5m -XX:MaxPermSize5m【JDK<1.6】
     *
     * @param args
     */
    public static void main(String[] args) { List<String> list = new ArrayList<>(); int i = 
           

運作結果: 

JDK1.6

 :Perm space 

JDK1.7

 :heap space

【注】

/**
     *String.intern()方法傳回字元串常量池引用,但不一定每時每刻都傳回一樣,可能垃圾回收後重新放入常量池
     *
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(System.identityHashCode((args[
           

淺堆和深堆

淺堆(shallow heap):一個對象結構所占的記憶體大小,對象包括屬性和對象頭、對象引用等。

如String對象,其結構包括:
類型 大小
int hash32
int hash
ref value c://...

其中2個int8位元組 對象引用4位元組 對象頭8位元組 按照8位元組對齊,則對象淺堆共24位元組

深堆(retained heap):一個對象被GC回收後,可以真實釋放的記憶體大小。即對象所持有的對象和包括對象自身的所有的淺堆的大小之和。

從圖中可以看出對象A的淺堆大小為A本身,對象A的實際大小為對象A、對象B、對象C、對象D的淺堆大小之和,對象A的深堆大小為對象A和對象C,因為對象B和對象D同時也被對象E所引用

轉載于:https://www.cnblogs.com/htkj/p/10932489.html