- 配置VM arguments:
-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
可以显示内存状态等信息
堆溢出
- 测试代码
public class testOom {
static class OOMObject{};
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>();
while(true){
list.add(new OOMObject());
}
}
}
- 异常提示:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
- 解决方案
- 通过内存映象分析工具(如EclipseMemory Analyzer)对Dump出来的堆转储快照进行分析,确认内存中的对象是否是必要的,也就是分析到底是出现内存泄漏还是内存溢出
- 如果是内存泄漏,通过工具查看泄漏对象到GC Roots的引用链
- 如果没有内存泄漏
- 检查堆参数(-Xmx与-Xms)是否偏小;
- 代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况
虚拟机栈和本地方法栈溢出
Java虚拟机规范描述了两种异常:
- 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError
- 如果虚拟机再扩展时无法申请到足够的内存空间,抛出OutOfMemoryError
示例:无法跳出的递归
public class testOom2 {
private int stackLength = -1;
public void stackLeak(){
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable {
testOom2 oom = new testOom2();
try{
oom.stackLeak();
}catch(Throwable e){
System.out.println(oom.stackLength);
throw e;
}
}
}
方法区和运行时常量池溢出
书中示例使用String.intern(),不过JDK1.7以上版本用书中代码不会出错;
书中另一个示例用了CGLib直接操作字节码运行时生成大量动态类
本机直接内存溢出
-XX: MaxDirectMemorySize