为什么这段代码抛出StackOverflowException而不是OutOfMemoryException?

时间:2013-10-23 04:13:42

标签: java out-of-memory stack-overflow

由于嵌套构造函数调用,我有以下代码及其抛出StackOverflowException,并且我知道只有在构造函数成功运行时才会分配内存。

package interview;

public class StackOverflow {
    int i;
    StackOverflow()
    {
            System.out.println(" i= "+i);
        System.out.println("in Constructor");
        StackOverflow sOf = new StackOverflow();
        sOf.i=5;
        System.out.println(" i= "+i);
    }
    public static void main(String[] args) {
        System.out.println("in main");
        StackOverflow s = new StackOverflow();
        s.i=10;
        System.out.println(" i= "+s.i);
    }

}

所以我怀疑这是'i'的价值发生了什么?它是存储在堆栈还是堆中的某个地方? 在这种情况下,上面的代码可以抛出以下异常?

  

OutOfMemoryException异常

4 个答案:

答案 0 :(得分:2)

OutOfMemoryError:当Java虚拟机由于内存不足而无法分配对象时抛出,垃圾收集器不再提供更多内存。

StackOverflowError:当发生堆栈溢出时抛出,因为应用程序过于冗长。

  

在哪种情况下它可以抛出OutOfMemoryError?

  • 你的构造函数递归地调用自己进入更深层, 堆栈在JVM内存不足之前溢出。

    而不是递归使用for循环来创建太多对象。您 也许可以看到OutOfMemoryError

  

我的问题是i的值发生了什么(它正在获取存储的堆或堆栈):

  • JVM specification-2.5.2明确指出:

      

    Java虚拟机堆栈类似于a的堆栈   传统语言如C:它包含局部变量和部分   结果,并在方法调用和返回中起作用。

    由于堆是对象的存储空间,而i是您的对象的字段成员 StackOverflow类,它存储在Heap

答案 1 :(得分:1)

启动JVM时,会从操作系统为其分配一些内存。 jvm使用这个内存来处理它的purpuses。 JVM以多种方式使用此内存 - 如堆栈和堆。

每当调用一个方法时,该方法中的参数,返回值和其他局部变量等数据都保存在堆栈中。调用该方法时会创建此堆栈,并在方法完成执行时销毁该堆栈。如果你继续从一个方法调用一个方法,那么就会出现一些瓶颈,它将显示一个StackOverFlowError。但是在堆的情况下--JVM从这个堆中为新对象分配内存。如果您有对象的引用,并且堆中剩余的可用空间非常少,它将显示OutOfMemoryError。

答案 2 :(得分:0)

启动JVM时,您可以定义可用于处理的RAM量。 JVM将其划分为某些内存位置以用于其处理目的,其中两个是Stack& Heap

OutOfMemoryError与Heap有关。如果在memeory中有大对象(或)引用的对象,那么您将看到OutofMemoryError

StackOverflowError与堆栈有关。所有局部变量和方法调用相关数据都将在堆栈中。对于每个方法调用,将创建一个堆栈帧,并且本地以及与方法调用相关的数据将被放置在堆栈帧内。方法执行完成后,将删除堆栈帧。重现这一点的一种方法是,对于方法调用有无限循环,你会看到stackoverflow错误,因为堆栈帧将填充每个调用的方法数据,但它不会被释放(删除)。 / p>

在你的情况下,你正在调用导致堆栈溢出而不是堆的构造函数,因此得到StackOverflowError而不是OutOfMemoryError

StackOverflow()
    {                        
        StackOverflow sOf = new StackOverflow(); //causing Stack to overflow.**                       
    }

i的值始终为0,即默认值。

请参阅this

答案 3 :(得分:0)

无论何时调用另一个函数内的函数,第二个函数都位于堆栈的顶部。因为你已经对构造函数进行了递归调用,所以由于你的新构造函数,它会不断增加你的Stack大小。如果没有空间在主堆栈中创建新的构造函数条目, JVM 将抛出StackOverflowException

对于OutofMemoryException,您只需要创建尽可能多的对象,以便中没有剩余空间。

Class variables and Objects are created in Heap and function calls, and local variables are maintained in Stack.

iclass variable,因此会存储在Heap中。并且由于它在声明时未定义,因此将获得int的默认值,即0。您的构造函数永远不会到达您将值5赋给i的行。因此,它始终具有值0