[英]Java : recursive constructor call and stackoverflow error
请帮忙理解为什么以下代码
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,直到我读到以下线程。
这说
3. The object is fully constructed/created when the constructor returns.
从我可以收集的,构造函数是一个方法,因为堆内存比堆栈内存大得多,递归构造函数调用导致StackOverflowError。 它是否正确 ?
由于给定代码中的对象不会被完全创建,构造函数的堆栈帧分配实际上会发生吗?
--edit--对于指出的重复项,我确实理解StackoverflowError是什么。 我在问题中提到过“在研究中,我发现java构造函数被认为是一种方法,它解释了StackOverflowError”。 我的问题是要理解构造函数是否像其他方法一样获取堆栈帧,因为在构造函数返回之前对象创建尚未完成。 希望这澄清一下。
每当调用构造函数时,其return address
被压入堆栈 。 由于堆栈是有限的并且小于堆内存,因此会出现类似StackOverflowError
而不是OutOfMemoryError
。
构造函数是一个方法,由于堆内存比堆栈内存大得多,因此递归构造函数调用导致StackOverflowError。 它是否正确 ?
是的,你的疯狂猜测是完全正确的。 干杯!
构造函数是一种方法,也就是函数。 每次调用它时,都会将一块内存分配给堆栈 ,以存储函数的变量。
您的代码无限制地创建对构造函数的调用,将内存分配给堆栈直到内存完成。
您正在获取StackOverflowError
而不是OutOfMemoryError
,因为专用于堆栈的内存量小于专用于堆的内存量。
编辑:我已经使用您的代码做了一些测试。 我已经指定了8M( -Xms8M -Xmx8M
)的堆内存空间和100M( -Xss100M
)的堆栈内存空间。 计算结果始终是错误StackOverflowError
。
然后,这可能意味着在这种情况下没有为堆分配内存 。 正如你在问题中所述:
构造函数返回时,对象是完全构造/创建的。
你是对的:堆栈比堆小得多,并且不会完全创建任何对象。
基本上你所说的是正确的,堆栈空间在堆空间之前耗尽。
根据java,所有引用变量都存储在堆栈内存空间中,堆栈内存空间小于堆空间,这就是我们得到的堆栈空间溢出异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.