java.lang.OutOfMemoryError

当你看到OutOfMemoryError,应该怎么办?如果只是想到设置-Xmx值更大些,可能是不够的。因为有多种不同的情形,都可以导致OutOfMemory错误。

  • java.lang.OutOfMemoryError: Java heap space
  • java.lang.OutOfMemoryError: PermGen space
  • java.lang.OutOfMemoryError: unable to create new native thread
  • java.lang.OutOfMemoryError: GC Overhead limit exceeded
  • java.lang.OutOfMemoryError: Requested array size exceeds VM limit
  • java.lang.OutOfMemoryError: Metaspace
  • java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?
  • java.lang.OutOfMemoryError: Compressed class space
  • java.lang.OutOfMemoryError: reason stack_trace_with_native_method

Java heap space
这个可能是最常见的OutOfMemory了。这个问题通过增大参数-Xmx[g|m|k]也许可以解决。当然,更踏实的做法还是要检测程序是不是有内存泄漏的问题。

PermGen space
通过参数-XX:PermSize=[g|m|k]进行调整。在JDK8之后,Permanent Generation这块heap内存已经放弃,而和Native Memory合并了。

unable to create new native thread

Java虚拟机中每创建的一个线程,就需要在操作系统中对应的创建一个线程。这个错误提示,就是说操作系统已经不能创建更多线程给JVM使用了。我们使用线程一般是基于线程池的。出现这个错误提示,那基本上说明程序执行过程中有线程被大量的创建出来,一定要好好去检查一下代码了。不同的操作系统支持的线程数不同,可以通过简单的小程序跑跑看。对于Linux系统来说,线程数的限制不是基于进程的,而是针对整个操作系统的。可以通过cat /proc/sys/kernel/threads-max查看最大线程数。

ulimit -s  256
ulimit -i  120000
echo 120000 > /proc/sys/kernel/threads-max
echo 600000 > /proc/sys/vm/max_map_count
echo 200000 > /proc/sys/kernel/pid_max 

这种类型的OOM不能通过-XX:+HeapDumpOnOutOfMemoryError参数dump出文件。

private static void createInfinitThreads() {
    long i = 0;
    while(true){
        new Thread(new Runnable(){
            public void run() {
                try {
                    Thread.sleep(10000000);
                } catch(InterruptedException e) { }
            }
        }).start();

        i ++;
        System.out.println(i);
    }
}

这个网页介绍JVM内存很清楚。Java内存区域与内存溢出异常

图一:

图二:下面中的Permanent区域在Java8中已经和method area合并。

图三:

Reference: