zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【JVM与性能调优】JVM的StackOverflowError介绍

JVM性能 介绍 调优
2023-09-14 09:04:55 时间

一、JVM中StackOverflowError的概念

StackOverflowError是Java虚拟机抛出的一种错误
它表示线程的调用栈太深而导致栈溢出。

二、JVM中StackOverflowError的产生原因

当一个线程调用的方法太多,导致方法调用栈的深度超过了虚拟机所允许的最大深度时,就会抛出StackOverflowError。

在Java虚拟机规范中,每个线程都有一个私有的Java虚拟机栈,用于存储方法调用的状态。
每个方法被调用时,都会在栈中创建一个新的栈帧,用于存储该方法的局部变量、操作数栈、方法返回地址等信息。当方法返回时,该栈帧会被弹出,恢复上一个栈帧的状态。

当一个线程的Java虚拟机栈空间不足时,就会抛出StackOverflowError。
Java虚拟机规范中规定了每个线程的Java虚拟机栈的最大深度,如果超过了这个深度,就会抛出StackOverflowError。

三、如何避免StackOverflowError ?

为了避免StackOverflowError,可以考虑以下几点:

  • 减少方法调用的深度,尽量避免递归调用;
  • 增加Java虚拟机栈的大小,可以通过-Xss参数来指定Java虚拟机栈的大小;
  • 优化代码,减少方法调用的次数。

四、可能导致StackOverflowError的代码示例1

以下是一个可能导致StackOverflowError的代码示例:

public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        main.methodA();
    }
    public void methodA() {
        methodB();
    }
    public void methodB() {
        methodA();
    }
}

在上面的代码中,methodA和methodB互相调用,没有终止条件,因此会导致栈溢出,抛出StackOverflowError。

五、可能导致StackOverflowError的代码示例2

5.1 编写如下代码

// JVM设置 ‐Xss128k(默认1M)

 public class StackOverflowTest {
     static int count = 0;
     static void redo() {
         count++;
         redo();
     }
     public static void main(String[] args) {
         try {
             redo();
         } catch (Throwable t) {
             t.printStackTrace();
             System.out.println(count);
         }
     }
 }

5.2 查看运行结果

java.lang.StackOverflowError
at com.tuling.jvm.StackOverflowTest.redo(StackOverflowTest.java:12)
at com.tuling.jvm.StackOverflowTest.redo(StackOverflowTest.java:13)
at com.tuling.jvm.StackOverflowTest.redo(StackOverflowTest.java:13)

5.3 结论

-Xss设置越小count值越小,说明一个线程栈里能分配的栈帧就越少,但是对JVM整体来说能开启的线程数会更多
JVM内存参数大小该如何设置?
JVM参数大小设置并没有固定标准,需要根据实际项目情况分析,给大家举个例子
日均百万级订单交易系统如何设置JVM参数