Java中的OOM
- java.lang.StackOverflowError
- java.lang.OutMemoryError:Java heap space
- java.lang.OutMemoryError:GC overhead limit exceeded:Gc回收时间过长会发生outofmemoryerror,过长的定义是,如果超过98%的时间来做GC,并且回收了不到2%的堆内存,连续多次回收不到2%的情况会跑出,负责形成恶性循环,gc清理的内存再次被填满,迫使gc再次执行。
/* -Xmx10m -Xms10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m */ public static void main(String[] args){ int i = 0; List<String> list = new ArrayList<>(); try{ while (true){ list.add(String.valueOf(new Random().nextInt(1111111)).intern()); } }catch (Throwable e){ e.printStackTrace(); } }
- java.lang.OutMemoryError:Direct buffer memory:写NIO程序使用ByteBuffer来读取或者写入数据,这是基于通道(channel)和缓冲区(buffer)的IO方式,可以使用Native函数库直接分配堆内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作,这样在一些场景中能够提高性能,避免了Java堆和native堆中来回复制数据。
- ByteBuffer.allocate(capability)第一种方式分配JVM内存,属于GC管辖范围,需要拷贝所以速度相对较慢
- ByteBuffer.allocateDirect(capability)第二种方式分配OS本地内存,不属于GC管辖范围,由于不需要内存拷贝,故而速度较快
/* -Xmx10m -Xms10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m */ static void directMemory(){ System.out.println("配置的MaxDirectMemory:" + sun.misc.VM.maxDirectMemory()/ (double)1024 / 1024 + "MB"); ByteBuffer.allocateDirect(6 * 1024 * 1024); }
- java.lang.OutMemoryError:unable to create new native thread:在高并发请求服务器的时候,一个应用进程创建太多线程,超过系统的承载能力。你的服务器不允许应用程序创建这么多线程,Linux系统默认一个进程可以创建最多1024个线程(解决办法:减少线程创建或者修改默认服务器配置,扩大默认限制)。
- java.lang.OutMemoryError:Metaspace:java8metaspace取代永久代,使用本地内存进行存储。Metaspace是方法与在HotSpot中的实现,即在java8中,classe metadata被存储在Metaspace的native memory(永久代/metaspace:虚拟机加载的类型学,常量池,静态变量,即时编译后的代码)