java.lang.stackoverfloweror.

时间:2020-02-23 14:35:03  来源:igfitidea点击:

在本文中,我们将讨论 java.lang.StackOverflowError通过查看不同的代码示例,我们怎样才能避免它们。

更确切地说, StackOverflowError这是一个错误,Java不允许捕获空间堆栈,因为它是一个可以遇到的最常见的运行时错误之一,因为它的升高条件在几乎每个模块中直接或者间接地实现。

java.lang.stackoverfloweror的主要原因是我们尚未向我们的递归函数或者模板提供适当的终止条件,这意味着它将变成相当于无限循环。

JVM如何调用方法

了解 java.lang.StackOverflowError,我们需要了解JVM如何在内部调用方法。
调用方法时,在线程堆栈大小或者调用堆栈上创建一个新的堆栈帧。
现在,相应的堆栈帧保存调用方法的参数,主要是本地变量和该方法的返回地址。
这一堆栈帧的创建将是一个迭代过程,并且只有在嵌套方法中找到了方法调用的结束时,才会停止。

在这个整个过程中,如果JVM为新的堆栈框架耗尽空间,则会抛出一个 java.lang.StackOverflowError

(这是原因,为什么我们也称为JVM错误。)

java.lang.stackoverfloweror的原因

java.lang.StackOverflowError的可能原因有很多

没有终止条件

这是最常见的局面被称为未被终止或者无限递归。

让我们看看由于给定的条件而抛出错误的示例:

在以下示例中,我们正在尝试打印自然数字,而不提供适当的条件。

public class theitroad
{
    static int i=0 ; //declaring static variable it cannot be from a static context
    
    public static int printNum (int x) //declaring static because 
    //non-static method printNum(int) cannot be referenced from a static context
    {
        i=i+1;
        System.out.println(i);
        return i+ printNum(i+1) ;
    }
 
	public static void main (String[] args) { 
		theitroad.printNum(i) ;
	}
}

输出:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17. 

..
线程中的"main"java.lang.stackoverfloweror在oniToroad.printnum(onitad.java:8)on on innirad.printnum(onitad.java:8)在oninitorad.printnum(oniTorad .java:8)在oniToroad.printnum(onitad.java:8)在onintorad.printnum(oniToroad.java:8)on on inniradnum(onitad.java:8)

现在,我们可以看到由于缺少终止条件而错误被抛出。
另外,请注意,这些重复行号将是无限的,它们表示递归调用此函数。

解决方案

注意到这些重复模式后,尝试为递归调用引入终止条件或者某些基本条件。
另一种方法可以是,如果我们注意到我们已正确实现仍然遇到相同的错误,则可以避免通过增加堆栈的大小以允许更大数量的递归调用。
这可以通过更改编译器的设置来轻松完成。

public class theitroad
{
    static int i=0 ; //declaring static variable it cannot be from a static context
    
    public static int printNum (int x) //declaring static because 
    //non-static method printNum(int) cannot be referenced from a static context
    {
        i=i+1;
        System.out.println(i);
        
        if(i==20) //Terminating condition introduced
            return i;
        return i+ printNum(i+1) ;
    }
 
	public static void main (String[] args) { 
		theitroad.printNum(i) ;
	}
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

由于类之间的循环关系

循环关系:当两个不同的类在其构造函数内彼此实例化时会导致这种关系。

这最终有一个StackOverFloweror,因为类的构造函数是实例化ClassB的,并且ClassB的构造函数再次实例化Classa,并且它反复发生直到溢出。

public class A 
{
    public B type2 ;
    public A() {
        type2 = new B () ; //object of class B is created and hence constructor of //B is invoked
    }
 
    public static void main ( String[] args) {
        A type1 = new A () ; //starting the cycle by invoking class A constructor 
//at the time of object declaration (implicit)
    }
}
class B 
{
    public A type1 ;
    public B () {
        type1= new A () ; //object of class A is created and hence constructor of //A is invoked
    }
}

输出:

Exception in thread “main" java.lang.StackOverflowError  at B.(A.java:16)  at A.(A.java:5)  at B.(A.java:16)  at A.(A.java:5)  at B.(A.java:16)  at A.(A.java:5)  at B.(A.java:16)  at A.(A.java:5)  at B.(A.java:16)  at A.(A.java:5)  at B.(A.java:16)  at A.(A.java:5)  at B.(A.java:16)

此处的重复调用显示无限递归

解决方案

现在,这里的错误主要是由于构造函数重复互相调用,所以我们必须确保在实现不同的类时,不应出现上述条件。
由于这种循环构造函数的调用没有意义,因此我们可以避免它们,因为它们在创建各个类的对象时已经隐含地调用了它们。