Java:递归构造函数调用和stackoverflow错误

时间:2015-06-18 09:40:06

标签: java recursion constructor

请帮助理解为什么以下代码

public class HeapQn1 {

    /**
     * @param args
     */
    public HeapQn1() {
        new HeapQn1();
    }

    static HeapQn1 n = new HeapQn1();

    public static void main(String[] args) {

    }

}

结果

java.lang.StackOverflowError
    at com.rg.test.interview.HeapQn1.<init>(HeapQn1.java:8)
    at com.rg.test.interview.HeapQn1.<init>(HeapQn1.java:9)
    ...

根据我的理解,对象的内存分配发生在堆内存中,我期待OutOfMemoryError,因为在某些时候堆内存因为重复创建对象而已满。

在研究中,我发现java构造函数被认为是一个方法,它解释了StackOverflowError,直到我阅读了以下的线程。

When does the Constructor gets called in java?

3. The object is fully constructed/created when the constructor returns.

从我可以收集的内容来看,构造函数是一个方法,并且由于堆内存比堆栈内存大得多,因此递归构造函数调用导致了StackOverflowError。这是对的吗?

由于给定代码中的对象不会被完全创建,构造函数的堆栈帧分配是否会实际发生?

- edit-- 对于指出的重复项,我确实理解StackoverflowError是什么。我在问题中提到过#34;在研究中,我发现java构造函数被认为是一种方法,它解释了StackOverflowError&#34;。我的问题是要理解构造函数是否像其他方法一样获取堆栈帧,因为在构造函数返回之前对象创建尚未完成。希望这澄清。

5 个答案:

答案 0 :(得分:2)

每当调用构造函数时,其return address都会被推送到the stack。由于堆栈是有限的并且小于堆内存,因此您会收到类似StackOverflowError而非OutOfMemoryError的错误。

  

构造函数是一个方法,由于堆内存比堆栈内存大得多,因此递归构造函数调用导致StackOverflowError。这是对的吗?

是的,您的狂野猜测是完全正确的。干杯!

答案 1 :(得分:1)

构造函数是一个方法,也就是函数。每次调用它时,都会将一大块内存分配给堆栈,以存储函数的变量。

您的代码无限制地创建对构造函数的调用,将内存分配给堆栈直到内存完成。

您获得的是StackOverflowError而不是OutOfMemoryError,因为专用于堆栈的内存量小于专用于堆的内存量。

编辑:我已经使用您的代码进行了一些测试。我已经指定了8M(-Xms8M -Xmx8M)的堆内存空间和100M(-Xss100M)的堆栈内存空间。计算结果始终是错误StackOverflowError

然后,这可能意味着在这种情况下没有为堆分配内存。正如你在问题中所述:

  

当构造函数返回时,对象是完全构造/创建的。

答案 2 :(得分:0)

你是对的:堆栈比堆小得多,并且不会完全创建任何对象。

答案 3 :(得分:0)

基本上你所说的是正确的,堆空间在堆空间之前耗尽。

答案 4 :(得分:0)

按照Java,所有参考变量都存储在堆栈内存空间中,并且堆栈内存空间小于我们得到stackOverFlowException的堆空间。