OOM,即OutOfMemory,内存溢出
- OOM之 Java heap space
java堆内存溢出,一般由于内存泄漏或者堆内存大小设置不当引起
String str = "sherlock";
while (true) {
str += new Random(100000).nextInt() + new Random(20000000).nextInt();
str.intern();
}
byte[] b = new byte[80 * 1024 * 1024];
- OOM之GC overhead limit
GC回收时间过长,过长的定义是:超过98%的时间用来做GC并且回收了不到2%的堆内存,连续多次GC都只回收了不到2%的堆内存的极端情况才会抛出。
本质是一个预判性的异常,抛出该异常时系统没有真正的内存溢出。是由于垃圾回收效果不明显,或者垃圾回收效率不如分配效率高引起的。
public static void main(String args[]) throws Exception {
Map map = System.getProperties();
Random r = new Random();
while (true) {
map.put(r.nextInt(), "value");
}
}
https://plumbr.io/outofmemoryerror/gc-overhead-limit-exceeded
- OOM之Direct buffer memory
直接内存溢出,一般发生在NIO中(NIO程序经常通过ByteBuffer来读取或写入数据)
public static void main(String[] args) {
System.out.println("配置的maxDirectMemory:" +
(sun.misc.VM.maxDirectMemory() / (double) 1024 / 1024 + "MB"));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
- OOM之unable to create new native thread
产生原因:
- 你的应用创建了太多的线程,一个应用进程创建多个线程,超过系统承载极限
- 你的服务器并不允许你的应用程序创建这么多线程,linux系统默认允许单个进程可以创建的线程数是1024个。你的应用创建超过这个数据,就会报java.lang.OutOfMemoryError:unable to create new native thread.
解决办法: - 想办法降低你应用程序创建线程的数量,分析应用是否真的需要创建这么多线程,如果不是,改代码将线程数降到最低。
- 对于有的应用,确实需要创建很多线程,远超过linux系统默认的1024个线程的限制,可以通过修改linux服务器配置,扩大linux默认限制
public static void main(String[] args) {
for (int i = 0; ; i++) {
System.out.println("*********************i=" + i);
new Thread(() -> {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "" + i).start();
}
}
- OOM之Metaspace
元空间溢出
JDK1.8以后,Metaspace是方法区在Hotspot中的实现,它与持久代最大的区别在于:Metaspace并不在虚拟机内存中而是使用本地内存
网友评论