0

由于嵌套的构造函数调用,我有以下代码及其抛出 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' 的值发生了什么?它是否存储在堆栈或堆中的某个位置?在什么情况下上面的代码会抛出下面的异常?

内存不足异常

4

4 回答 4

2

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

StackOverflowError:由于应用程序递归太深而发生堆栈溢出时抛出。

在这种情况下它会抛出 OutOfMemoryError?

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

    而不是递归使用for循环来创建太多的对象。你也许能看到OutOfMemoryError.

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

  • JVM 规范 2.5.2明确指出:

    Java 虚拟机堆栈类似于 C 等传统语言的堆栈:它保存局部变量和部分结果,并在方法调用和返回中发挥作用。

    由于堆是对象的存储并且iStackOverflow类的字段成员,因此它存储在Heap

于 2013-10-23T04:19:05.270 回答
1

当您启动 JVM 时,操作系统会为它分配一些内存。jvm 将此内存用于其处理目的。JVM 以多种方式使用此内存 - 例如堆栈和堆。

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

于 2013-10-23T04:31:09.693 回答
0

每当你在另一个函数中调用一个函数时,第二个函数就会出现在堆栈的顶部。并且由于您已经对构造函数进行了递归调用,因此由于您的新构造函数,它会不断增加您的堆栈大小。当主堆栈中没有剩余空间来创建新的构造函数条目时,JVM会抛出异常StackOverflowException

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

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

i是 a class variable,所以它被存储在Heap. 并且由于它在声明时没有定义,它将获得 int ie 的默认值0。您的构造函数永远不会到达您将值分配给的5i。因此,它将始终具有价值0

于 2013-10-23T04:28:17.087 回答
0

当你启动 JVM 时,你定义了它可以使用多少 RAM 来进行处理。JVM 将其划分为某些内存位置以用于处理目的,其中两个是Stack&Heap

OutOfMemoryError与堆有关。如果内存中有大对象(或)引用的对象,那么您将看到OutofMemoryError.

StackOverflowError与堆栈有关。您所有的局部变量和方法调用相关数据都将在堆栈上。对于每个方法调用,将创建一个堆栈框架,并且本地以及与方法调用相关的数据将放置在堆栈框架内。一旦方法执行完成,堆栈帧将被删除。重现此问题的一种方法是,对方法调用进行无限循环,您将看到stackoverflow错误,因为每次调用的堆栈帧都将填充方法数据,但不会被释放(删除)。

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

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

i值将始终为0默认值。

请参考这个

于 2013-10-23T04:16:13.880 回答