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)存放的信息:

  • 虚拟机加载的类信息
  • 常量池
  • 静态变量
  • 即时编译后的代码

每日一言:

有目标不一定怎么样,没目标一定不能怎么样。

猜你喜欢

转载自blog.csdn.net/qq_41216743/article/details/102732700
OOM
今日推荐