生活中的美酒, 线上的OOM, 今天我们分析下常见的java 内存溢出和解决办法. 结合其他大神的笔记, 自己记录下
oom_1.jpg
Java堆溢出
demo:
package com.ck.wyy.basic;
import java.util.ArrayList;
import java.util.List;
public class OOM {
static class OOMObject {
}
public static void main(String[] args) {
oom_test1();
}
private static void oom_test1() {
List<OOMObject> list = new ArrayList<OOMObject>();
//在堆中无限创建对象
while (true) {
list.add(new OOMObject());
}
}
}
常见错误如下:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:261)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
at java.util.ArrayList.add(ArrayList.java:458)
分析思路:
使用Jprofiler dump文件分析
- 栈溢出
一般会报2种错误:
如果虚拟机栈可以动态扩展, 当扩展时无法申请足够内存,会报错oom
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError 异常;
关联tips:通过-Xss设置的每个线程栈大小.
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
- 方法区溢出
方法区,又称元数据区, 是存储什么地方的? 是存储一些class信息, 比如反射产生大量的类.
- 虚拟机参数:-XX:MetaspaceSize=10M -XX:MaxMetaspaceSize=10M
- 直接内存溢出
本机直接内存的分配虽然不会受到Java 堆大小的限制,但是受到本机总内存大小限制。直接内存由 -XX:MaxDirectMemorySize 指定,如果不指定,则默认与Java堆最大值(-Xmx指定)一样。 NIO程序中,使用ByteBuffer.allocteDirect(capability)分配的是直接内存,可能导致直接内存溢出
ByteBuffer bb = ByteBuffer.allocateDirect(10241024128);
- GC overhead limit exceeded
说明:
这个是JDK6新加的错误类型,一般都是堆太小导致的。Sun 官方对此的定义:超过98%的时间用来做GC并且回收了不到2%的堆内存时会抛出此异常
常见OOM总结:
java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: unable to create new native thread
java.lang.OutOfMemoryError: Metaspace
java.lang.OutOfMemoryError: Direct buffer memory
java.lang.OutOfMemoryError: GC overhead limit exceeded
网友评论