测试环境JDK1.8
给每个栈分配的内存越大,反而越容易出现OOM异常
原因:操作系统给每个进程分配的内存是有限制的,比如32位windows的单个进程的最大内存为2GB。HotSpot虚拟机提供了参数可以控制java堆和方法区这两部分的最大值,剩余的内存即为2GB减去最大堆容量,再减去最大方法区容量,程序计数器耗内存很少,可以忽略掉,如果把直接内存和虚拟机进程自身消耗的内存也去掉的话,剩余的内存就由虚拟机栈和本地方法栈来分配了。
虚拟机栈和本地方法栈内存=2G-最大堆容量-最大方法区容量-程序计数器-直接内存-虚拟机自身内存
- 堆容量 -Xss
- 方法区容量
JDK1.6之前称之为老年代或永久代
-XX:PermSize 初始值
-XX:MaxPermSize 最大值 - 程序计数器可以忽略;
- 直接内存如果不调用native方法,则为0;
- 虚拟机自身内存可以看成固定值;
那么最大线程数=(虚拟机栈+本地方法栈内存)/单个线程分配的内存
设置最大堆大小,那么根据公式,可以算出最大线程数,原例子中的大小为2M,说明允许线程数很大,需要半天才能复现,我的机器是8G64位的,个人觉得直接弄很大,假设总共为2G内存,-Xss设置为1.5G,则很快复现问题。
/**
* VM Args:-Xss2M (这时候不妨设大些,请在32位系统下运行)
*
* @author zzm
*/
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();
}
}