OutOfMemoryError
StackOverflowError
栈满会抛出该错误。无限递归就会导致StackOverflowError,是java.lang.Throwable→java.lang.Error→java.lang.VirtualMachineError下的错误。详见StackOverflowErrorDemo。
public class StackOverflowErrorDemo {
public static void main(String[] args) {
stackOverflowError();
}
private static void stackOverflowError() {
stackOverflowError();
}
}

OOM—Java head space
堆满会抛出该错误。详见JavaHeapSpaceDemo。
//-Xms10m -Xmx10m -XX:MaxDirectMemorySize=5m -XX:+PrintGCDetails
public class JavaHeapSpaceDemo {
public static void main(String[] args) {
String str = "abc";
while (true) {
str += str + new Random().nextInt(111111) + new Random().nextInt(222222);
str.intern();
}
}
}

OOM—GC overhead limit exceeded
这个错误是指:GC的时候会有“Stop the World",STW越小越好,正常情况是GC只会占到很少一部分时间。但是如果用超过98%的时间来做GC,而且收效甚微,就会被JVM叫停。下例中,执行了多次Full GC,但是内存回收很少,最后抛出了OOM:GC overhead limit exceeded错误。详见GCOverheadDemo。
//-Xms10m -Xmx10m -XX:MaxDirectMemorySize=5m -XX:+PrintGCDetails
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();
throw e;
}
}
}

OOM—GC Direct buffer memory
在写NIO程序的时候,会用到ByteBuffer来读取和存入数据。与Java堆的数据不一样,ByteBuffer使用native方法,直接在堆外分配内存。当堆外内存(也即本地物理内存)不够时,就会抛出这个异常。详见DirectBufferMemoryDemo。
//-Xms10m -Xmx10m -XX:MaxDirectMemorySize=5m -XX:+PrintGCDetails
public class DirectBufferMemoryDemo {
public static void main(String[] args) {
System.out.println("配置的maxDirectMemory: " + (sun.misc.VM.maxDirectMemory() / (double) 1024 / 1024) + "MB");
try {
Thread.sleep(300);
} catch (Exception e) {
e.printStackTrace();
}
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
}

OOM—unable to create new native thread
在高并发应用场景时,如果创建超过了系统默认的最大线程数,就会抛出该异常。Linux单个进程默认不能超过1024个线程。解决方法要么降低程序线程数,要么修改系统最大线程数vim /etc/security/limits.d/90-nproc.conf。详见UnableCreateNewThreadDemo
public class UnableCreateNewThreadDemo {
public static void main(String[] args) {
for (int i = 0; ; i++) {
System.out.println("**********" + i);
new Thread(() -> {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (Exception e) {
e.printStackTrace();
}
}, i + "").start();
}
}
}

OOM—Metaspace
元空间满了就会抛出这个异常。