StackOverFlowError原因和解决办法

StackOverFlowError原因和解决办法StackOverFlowError是常见的JVM错误之一。在此博客文章中,我们将研究线程堆栈的内部机制,可能触发StackOverFlowError的原因以及解决此错误的潜在解决方案。为了更深入地了解StackOverFlowError,让我们回顾一下这个简单的程序:1publicclassSimpleExample{2​3publicstaticvoidmain(Stringargs[]){4​5a()6…

StackOverFlowError是常见的JVM错误之一。在此博客文章中,我们将研究线程堆栈的内部机制,可能触发StackOverFlowError的原因以及解决此错误的潜在解决方案。

为了更深入地了解StackOverFlowError,让我们回顾一下这个简单的程序:

 

1
public class SimpleExample {

2

3
      public static void main(String args[]) {

4

5
            a()
6
      }
7

8
      public static void a() {

9

10
            int x = 0;
11
            b();
12
      }
13

14
      public static void b() {

15

16
            Car y = new Car();
17
            c();
18
      }
19

20
      public static void c() {

21

22
            float z = 0f;
23
      System.out.println(“Hello”);
24
      }
25
}
 

 

该程序非常简单,具有以下执行代码:

  1.  main() 首先调用方法
  2.  main() 方法调用 a()  方法。在a() 方法内部 ,整数变量“ x”被初始化为值0。
  3.  a() 方法反过来调用 b() 方法。在b() 方法内部 ,构造了Car对象并将其分配给变量“ y”。
  4.  b() 方法反过来调用该 c() 方法。在c() 方法内部 ,浮点变量“ z”被初始化为值0。

现在,让我们回顾一下执行上述简单程序时幕后发生的事情。应用程序中的每个线程都有其自己的堆栈。每个堆栈都有多个堆栈帧。线程按执行顺序将其正在执行的方法,原始数据类型,对象指针和返回值添加到其堆栈帧中。

StackOverFlowError原因和解决办法

1:线程的堆栈框架

步骤#1 main() 方法被推入应用程序线程的堆栈中。

步骤#2 a() 方法被推入应用程序线程的堆栈中。在 a() 方法中,原始数据类型‘int’定义为值0,并分配给变量x。该信息也被推入相同的堆栈框架中。请注意,两个数据(即“ 0”和变量“ x”)都被压入线程的堆栈框架中。

步骤#3 b() 方法被推入线程的堆栈。在该 b() 方法中,将创建Car对象并将其分配给变量“ y”。这里要注意的关键点是,“ Car”对象是在堆中创建的,而不是在线程的堆栈中创建的。只有Car对象的引用(即y)存储在线程的堆栈框架中。

步骤#4 c() 方法被推入线程的堆栈。在 c() 方法中,原始数据类型“ float”定义为值0f并分配给变量z。此信息也被推入相同的堆栈框架。请注意,两个数据(即“ 0f”和变量“ z”)都被压入线程的堆栈框架中。

一旦每个方法的执行完成,就将方法和变量/对象指针存储在堆栈帧中,如图2所示。

StackOverFlowError原因和解决办法

2:执行方法后的线程堆栈框架

是什么导致StackOverflowError

如您所见,线程的堆栈存储着它正在执行的方法,原始数据类型,变量,对象指针和返回值。所有这些都会消耗内存。如果线程的堆栈大小超出分配的内存限制,则会 StackOverflowError 抛出该错误。让我们看一下下面的bug程序,它会导致  StackOverflowError

 

1
public class SOFDemo {

2

3
         public static void a() {

4

5
                  // Buggy line. It will cause method a() to be called infinite number of times.
6
                  a();
7
         }
8

9
         public static void main(String args[]) {

10

11
                   a();
12
         }
13
}

 

在此程序中, main() 方法调用 a()  方法。 a() 方法递归调用自身。此实现将导致  a() 方法被无限次调用。在这种情况下, a() 方法将无限次添加到线程的堆栈帧中。因此,经过数千次迭代后,将超出线程的堆栈大小限制。一旦超过堆栈大小限制,将导致  StackOverflowError

 

1
Exception in thread “main” java.lang.StackOverflowError
2
       at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
3
       at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
4
       at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
5
       at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
6
       at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
7
       at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
8
       at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
9
       at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)

StackOverFlowError原因和解决办法

3StackOverflowError进度

StackOverflowError有什么解决方案?

有两种策略可以解决  StackOverflowError

1.修改代码

由于进行了非终止的递归调用(如上例所示),因此线程堆栈大小可能会增大到较大的大小。在这种情况下,您必须修复导致递归循环的源代码。引发“ StackOverflowError”时,它将打印递归执行的代码的堆栈跟踪。此代码是开始调试和解决问题的良好指针。在上面的示例中,它就是 a()  方法。

2.增加线程堆栈大小(-Xss

可能有正当理由需要增加线程堆栈大小。也许线程必须执行大量方法或很多局部变量/已在执行线程的方法中创建?在这种情况下,可以使用JVM参数‘-Xss增加线程的堆栈大小。启动应用程序时需要传递此参数。

 

1

– Xss2m

 

这会将线程的堆栈大小设置为2 mb

可能会带来一个问题:默认线程的堆栈大小是多少?默认线程堆栈大小根据您的操作系统,Java版本和供应商而异。

JVM版本

线程堆栈大小

Sparc 32位JVM

512k

Sparc 64位JVM

1024k

x86 Solaris / Linux 32位JVM

320K

x86 Solaris / Linux 64位JVM

1024K

Windows 32位JVM

320K

Windows 64位JVM

1024K

 

 

今天的文章StackOverFlowError原因和解决办法分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/11998.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注