【问题标题】:Java : recursive constructor call and stackoverflow errorJava:递归构造函数调用和stackoverflow错误
【发布时间】:2015-09-03 21:11:45
【问题描述】:

请帮助理解为什么下面的代码

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 。这是正确的吗?

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

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

【问题讨论】:

  • 你可以通过设置非常小的堆大小来测试......
  • @Raedwald - 我了解 StackOverflowError 是什么,我的问题是 1. 为什么代码没有以 OutOfMemoryError 结束 2. 构造函数是一种方法。
  • 我做了一些实证实验,并在我的回答中总结了它们。看看吧:)

标签: java recursion constructor


【解决方案1】:

根据java,所有引用变量都存储在堆栈内存空间中,堆栈内存空间小于堆空间,这就是我们得到stackOverFlowException。

【讨论】:

    【解决方案2】:

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

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

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

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

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

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

    【讨论】:

    • 不是反过来吗?
    • @Jagger 你为什么这么说?
    • 你写的是栈消耗的内存大于堆消耗的内存。我认为应该反过来。
    • 我的英文不太好,可能是我写错了。他得到的异常是StackOverflowError,那么栈的内存比堆的内存消耗的快,不是吗?
    • 好吧,从技术上讲不会,因为如果只有堆栈空间用完,那么在这种情况下你甚至不能说堆分配,对吗?
    【解决方案3】:

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

    构造函数是一个方法,由于堆内存远大于栈内存,递归构造函数调用导致StackOverflowError。这是正确的吗?

    是的,你的 wild 猜测是完全正确的。干杯!

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        基本上你说的没错,栈空间在堆空间用完之前就用完了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-26
          • 2013-04-23
          • 2012-08-31
          • 1970-01-01
          相关资源
          最近更新 更多