OOM问题定位与解决

OOM问题定位与解决

OOM类型

Java堆内存溢出

1
2
3
4
5
// 不断创建对象
List<byte[]> list = new ArrayList<>();
while (true) {
list.add(new byte[1024 * 1024]);
}

虚拟机栈溢出

1
2
3
4
// 递归调用
public void stackOverflow() {
stackOverflow();
}

方法区溢出

1
2
3
4
5
6
7
8
9
10
11
12
// 动态生成大量类
for (int i = 0; i < 100000; i++) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
return proxy.invokeSuper(obj, args);
}
});
enhancer.create();
}

定位工具

jmap

1
2
jmap -heap pid   # 堆信息
jmap -dump:format=b,file=heap.hprof pid # 导出堆

jstat

1
jstat -gc pid 1000  # 每秒GC信息

解决方案

  • 堆溢出:调整-Xmx,检查内存泄漏
  • 栈溢出:检查递归,检查-Xss
  • 方法区:减少动态类生成

总结

OOM问题需要结合工具和代码分析,找出根本原因才能有效解决。