请帮助理解为什么以下代码
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;。我的问题是要理解构造函数是否像其他方法一样获取堆栈帧,因为在构造函数返回之前对象创建尚未完成。希望这澄清。
答案 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的堆空间。