虚拟机栈和本地方法栈溢出
1.概述HotSpot虚拟机直接把虚拟机栈和本地方法栈合二为一,因此对于HotSpot来说,虽然-Xoss参数(设置本地方法栈大小)存在,但实际上是无效的,栈容量只由-Xss参数设定2.StackOverflowError如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常package com.java.one;/*** 栈深度大于虚拟机所允许最大深度
·
1.概述
HotSpot虚拟机直接把虚拟机栈和本地方法栈合二为一,因此对于HotSpot来说,虽然-Xoss参数(设置本地方法栈大小)存在,但实际上是无效的,栈容量只由-Xss参数设定
2.StackOverflowError
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常
package com.java.one;
/**
* 栈深度大于虚拟机所允许最大深度导致StackOverflowErroe
* 以单线程为例
* VM Args: -Xss128K(-Xss虚拟机栈)
* */
public class JavaVMStackSOF {
private int stackLength = 1;
public void stackLeak () {
stackLength++;
stackLeak();
}
public static void main(String[] args) {
JavaVMStackSOF javaVMStackSOF = new JavaVMStackSOF();
try {
javaVMStackSOF.stackLeak();
} finally {
System.out.println("栈深度stackLength: " + javaVMStackSOF.stackLength);
}
}
}
打印异常信息:
栈深度stackLength: 997
Exception in thread "main" java.lang.StackOverflowError
at com.java.one.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:13)
at com.java.one.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)
at com.java.one.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)
at com.java.one.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)
at com.java.one.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)
at com.java.one.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)
。。。
在单个线程下,无论是由于栈帧太大还是虚拟机栈容量太小(这里Xss为128K),当内存无法分配时,虚拟机抛出的都是StackOverflowError异常
3.OutOfMemoryError
如果虚拟机在扩展时无法申请到足够的内存空间,则抛出OutOfMemoryError异常
多线程下的内存溢出与栈空间是否足够大并不存在任何联系,换句话说,操作系统内存大小是有限制的,每个线程的栈分配的内存越大,可建立的线程数就越少,反而越容易产生内存溢出
操作系统分配内存=Xmx(堆最大容量)+MaxPermSize(方法区最大容量)+程序计数器消耗内存+虚拟机进程消耗内存+虚拟机栈和本地方法栈消耗内存
package com.java.one;
/**
* 创建线程导致内存溢出异常
* VM Args: -Xss2M(虚拟机栈容量Xss不妨设置大一些,可建立线程数就越少)
* 操作系统分配内存=Xmx(堆最大容量)+MaxPermSize(方法区最大容量)+程序计数器消耗内存+虚拟机进程消耗内存+虚拟机栈(本地方法栈)消耗内存
* */
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) {
JavaVMStackOOM javaVMStackOOM = new JavaVMStackOOM();
javaVMStackOOM.stackLeakByThread();
}
}
建立多线程导致内存溢出,在不能减少线程或更换64位虚拟机的情况下,只能通过减少堆最大容量和减少栈容量来换取更多的线程
更多推荐
已为社区贡献2条内容
所有评论(0)