jvm面試題---請談談你對 OOM 的認識?

JVM面試題——談談你對OOM的理解

java中的常見OOM有:

1、java.lang.StackOverflowError

2、java.lang.OutOfMemoryError: Java heap space

3、java.lang.OutOfMemoryError: GC overhead limit exceeded

4、java.lang.OutOfMemoryError: Direct buffer memory

5、java.lang.OutOfMemoryError : unable to create new native thread

6、java.lang.OutOfMemoryError: Metaspace

 

1、java.lang.StackOverflowError

  • 在一個函數中調用自己就會產生這樣的錯誤(棧溢出)
  • 發生區域:java虛擬機棧或本地方法棧

代碼實現:

public class StackOverflowErrorDemo {
    public static void main(String[] args) {
        stackOverflowError();
    }

    private static void stackOverflowError() {
        stackOverflowError();
    }
}

 


2、java.lang.OutOfMemoryError: Java heap space

  • new 一個很大對象,jvm堆內存不足時 
  • 發生區域:java堆

代碼實現:

/*
*
* -Xms20m -Xmx20m
*/
public class JavaHeapSpaceDemo {
    public static void main(String[] args) {
        //方式一
        /*String str = "lijiegui";
        while (true) {
            str += str + new Random().nextInt(1111);
            str.intern();
        }*/
        
        //方式二
        byte[] bytes = new byte[80*1024*1024];
    }
}

 


3、java.lang.OutOfMemoryError: GC overhead limit exceeded

  • 執行垃圾收集的時間比例太大, 有效的運算量太小,默認情況下,,如果GC花費的時間超過 98%, 並且GC回收的內存少於 2%, JVM就會拋出這個錯誤。

代碼實現:

//-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
public class GcOverheadDemo {
    public static void main(String[] args) {
        int i = 0;
        List<String> list = new ArrayList<>();

        try {
            while (true) {
                list.add(String.valueOf(++i).intern());
            }
        } catch (Exception e) {
            System.out.println("---i:" + i);
            e.printStackTrace();
        }
    }
}

 


4、java.lang.OutOfMemoryError: Direct buffer memory

原因:直接內存不足

寫NIO程序經常使用ByteBuffer來讀取或寫入數據,這是一種基於通道與緩衝區的I/O方式

ByteBuffer.allocate() 分配JVM堆內存,屬於GC管轄範圍,需要拷貝所以速度相對較慢

ByteBuffer.allocateDirect() 分配操作系統本地內存,不屬於GC管轄範圍,不需要內存拷貝所以速度相對較快

代碼實現:

//配置參數:-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
public class DirectBufferDemo {
    public static void main(String[] args) {
        System.out.println("maxDirectMemory : " + sun.misc.VM.maxDirectMemory() / (1024 * 1024) + "MB");
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
    }
}

 


5、java.lang.OutOfMemoryError : unable to create new native thread

  • 一個應用進程創建了多個線程,超過系統承載極限,Linux默認允許單個進程可以創建的線程數1024

代碼實現:

public class UnableCreateNewThreadDemo {
    public static void main(String[] args) {
        for (int i = 0; ; i++) {
            new Thread(() -> {
                try {
                    Thread.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }
    }
}  

 

6、java.lang.OutOfMemoryError: Metaspace

java8使用Metaspace代替永久代,與永久代最大的區別是:元空間並不在虛擬機內存中,而是使用本地內存。  

永久代(java8使用Metaspace)存放的信息:

  • 虛擬機加載的類信息
  • 常量池
  • 靜態變量
  • 即時編譯後的代碼

 

 

每日一言:

有目標不一定怎麼樣,沒目標一定不能怎麼樣。

 

發佈了63 篇原創文章 · 獲贊 9 · 訪問量 7125
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章