OutOfMemoryError异常:
1.java堆溢出
测试:java堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免自动扩展,然后不停的创建对象。
结果:java.lang.OutOfMemoryError:Java heap space...
2.运行时常量池溢出
测试:通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制了常量池的容量,然后通过String类的intern()方法来填充常量池。
结果:java.lang.OutOfMemoryError:PermGen space
3.方法区溢出
测试:同上通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,然后借助CGLib直接操作字节码运行时,生成大量的动态类。
结果:java.lang.OutOfMemoryError:PermGen space
4.虚拟机栈和本地方法栈溢出
测试:栈容量是由-Xss参数设定
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError
如果虚拟机在扩展栈时无法申请到足够的内存空间则抛出OutOfMemoryError
/**
* VM Args:-Xss128k
*
* @author ksfzhaohui
*
*/
public class JavaVMStackSOF {
private static Log logger = LogFactory.getLog(JavaVMStackSOF.class);
private int stackLength = 1;
public void stackLeak() {
stackLength++;
stackLeak();
}
public static void main(String[] args) {
JavaVMStackSOF oom = new JavaVMStackSOF();
try {
oom.stackLeak();
} catch (Throwable e) {
logger.info("stack length:" + oom.stackLength);
logger.error(e);
}
}
}
在单个线程下,无论是由于栈帧太大,还是虚拟机栈容量太小,当内存无法分配是,虚拟机都抛出StackOverflowError。
如果测试不限于单线程,通过不断的建立线程的方式倒是可以产生OutOfMemoryError
/**
* VM Args:-Xss2M
*
* @author ksfzhaohui
*
*/
public class JavaVMStackOOM {
private void dontStop() {
while (true) {
}
}
public void stackLeakByThread() {
while (true) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
thread.start();
}
}
public static void main(String[] args) throws Throwable {
JavaVMStackOOM oom = new JavaVMStackOOM();
oom.stackLeakByThread();
}
}
5.本机直接内存溢出
测试:通过-XX:MaxDirectMemorySize直接内存,通过ByteBuffer.allocateDirect方法分配内存,查看DirectByteBuffer类,其实内部真正分配内存的是UnSafe类
/**
* -Xmx20m -Xms20m -XX:MaxDirectMemorySize=10m
*
* @author ksfzhaohui
*
*/
public class DirectMemoryOOM {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) throws IllegalArgumentException,
IllegalAccessException {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
while (true) {
unsafe.allocateMemory(_1MB);
}
}
}
结果:
java.lang.OutOfMemoryError
参考:深入java虚拟机