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

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

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.(HeapQn1.java:8) at com.rg.test.interview.HeapQn1.(HeapQn1.java:9) ... 

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

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

什么时候在java中调用构造函数?

这说

 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

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

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

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

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