StackOverFlowError:原因和解决方案

StackOverFlowError:原因和解决方案StackOverFlowError是常见的JVM错误之一。在此博客文章中,让我们学习线程堆栈的内部机制。我们将探讨触发StackOverFlowError的原因以及解决该错误的潜在解决方案。为了更深入地了解StackOverFlowError,让我们回顾一下这个简单的程序:publicclassSimpleExample{ publicstaticvoidmai…

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

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

public class SimpleExample {

	public static void main(String args[]) {
		
		a();
	}	

	public static void a() {

		int x = 0;
		b();
	}

	public static void b() {

		Car y = new Car();		
		c();
	}

	public static void c() {

		float z = 0f;
		System.out.println("Hello");
	}
}

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

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

还请参见: Java的最新变化和下一步:“ OpenJDK是Java的未来”

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

Java

图1:线程的堆栈框架

在步骤1中:main()方法压入应用程序线程的堆栈。

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

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

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

每个方法的执行完成后,将删除方法和变量/对象指针(存储在堆栈框架中),如图2所示。

Java

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

是什么导致StackOverflowError?

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

public class SOFDemo {

	public static void a() {
			
		// Buggy line. It will cause method a() to be called infinite number of times.
		a();		
	}	
	
	public static void main(String args[]) {
		
		a();
	}
}

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

Exception in thread "main" java.lang.StackOverflowError
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
	at com.buggyapp.stackoverflow.SOFDemo.a(SOFDemo.java:7)
Java

图3:StackOverflowError进度

StackOverflowError有什么解决方案?

有两种策略可以解决StackOverflowError。

还请参见: Java应用程序的远程调试

1.修改代码

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

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

让我们探究需要增加线程的堆栈大小的合理原因。 也许线程必须执行大量方法,或者很多局部变量/已在该线程执行的方法中创建。 在这种情况下,您可以使用JVM参数’-Xss’增加线程的堆栈大小。 启动应用程序时需要传递此参数。

例:

-Xss2m

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

您可能想知道,默认线程的堆栈大小是多少? 为此,默认线程堆栈大小取决于您的操作系统,Java版本和供应商。

StackOverFlowError:原因和解决方案

翻译自: https://jaxenter.com/stackoverflowerror-causes-152027.html

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

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

(0)
编程小号编程小号

相关推荐

发表回复

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