java基础之OOM

生活中的美酒, 线上的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 list = new ArrayList();
//在堆中无限创建对象
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文件分析

  1. 栈溢出

一般会报2种错误:

如果虚拟机栈可以动态扩展, 当扩展时无法申请足够内存,会报错oom

如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError 异常;

关联tips:通过-Xss设置的每个线程栈大小.

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

  1. 方法区溢出

方法区,又称元数据区, 是存储什么地方的? 是存储一些class信息, 比如反射产生大量的类.

  • 虚拟机参数:-XX:MetaspaceSize=10M -XX:MaxMetaspaceSize=10M
  1. 直接内存溢出

本机直接内存的分配虽然不会受到Java 堆大小的限制,但是受到本机总内存大小限制。直接内存由 -XX:MaxDirectMemorySize 指定,如果不指定,则默认与Java堆最大值(-Xmx指定)一样。 NIO程序中,使用ByteBuffer.allocteDirect(capability)分配的是直接内存,可能导致直接内存溢出

ByteBuffer bb = ByteBuffer.allocateDirect(10241024128);

  1. 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

你可能感兴趣的:(java基础之OOM)