1 StackOverflowError
线程请求的栈深度大于虚拟机所允许的深度。
- 测试代码
/***
* 栈 测试类
*/
public class JavaVMStackSOF {
private static Integer count = 1;
public static void main(String[] args) {
a();
}
/***
* 通过递归方法调用
*/
public static void a() {
try {
count ++;
a();
}catch (Throwable e){
System.out.println(count);
System.out.println(e);
}
}
}
- 结果
设置不同的jvm参数,得到不同的结果
-Xss -X stack size 设置栈内存大小
-Dfile.encoding=UTF-8 -Xss128k
1000
java.lang.StackOverflowError
-Dfile.encoding=UTF-8 -Xss256k
2000
java.lang.StackOverflowError
-Dfile.encoding=UTF-8 -Xss1024k
7504
java.lang.StackOverflowError
- 解决方法 StackOverflowError异常的方法同样从内存大小和Java程序两个方面来解决问题。
1 内存大小: 增加每个线程的虚拟机栈大小,这种方式虽然简便,但在多线程的情况下,随着每个线程所属的虚拟机栈的大小的增加,所能执行的线程也就随之减少了
2 从Java程序上无疑就是检查是否出现方法的不合理递归调用,从而减少栈帧的创建和及时的回收。
我们使用这种方式来解决StackOverflowError异常时,通常要权衡这两个反比因素。
2 OutOfMemoryError
如果虚拟机栈可以动态扩展当扩展时无法申请到足够的内存时,就会OutOfMemoryError异常。
- 测试代码
public class JavaVMStackOOM {
public static void main(String[] args) {
b();
}
/***
* 不断的创建线程
*/
public static void b() {
while (true){
new Thread(() -> {
// 使用死循环 避免线程被回收
while (true){}
}).start();
}
}
}
- 结果
设置不同的jvm参数,得到不同的结果
-Xss -X stack size 设置栈内存大小
-Dfile.encoding=UTF-8 -Xss 2M
java的线程时映射到操作系统的内核线程上的,因此上述代码执行时有较大风险,可能会导致操作系统假死(果然死机了)。
如果虚拟机在拓展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。
在虚拟机栈和本地方法栈发生OOM异常场景如下:当Java 程序启动一个新线程时,若没有足够的空间为该线程分配Java栈(一个线程Java栈的大小由-Xss设置决定),JVM将抛出OutOfMemoryError异常
网友评论