当我在程序下面运行时
class Person{
Person p;
Person(){
System.out.println("Hi");
p = new Person();
}
}
public class Main {
public static void main(String[] args) {
new Person();
}
}
它抛出StackOverFlow错误 但我希望它是OOME,因为我们正在创建对象,而不是使用任何本地方法/变量或引用变量
答案 0 :(得分:4)
你是递归的,没有终止条件调用Person()
构造函数,它将数据放在堆栈上(至少,返回地址 - 堆栈不仅用于局部变量和参数):
Person(){
p = new Person(); // <<== Calls the Person() constructor, which again calls the Person() constructor, which again ...
}
因此,您会收到堆栈溢出错误。
理论上,编译器可以看到这是一个尾递归并优化了方法调用,但这不会发生。
Person
对象本身是在堆上创建的,但通常堆大于堆栈(至少在默认情况下是这样),因此堆栈早于堆填充。
尝试使用不同的堆栈大小和最大堆大小设置运行相同的应用程序,例如
java -Xss128M -Xmx4M Person
你会得到一个OOME而不是堆栈溢出。
答案 1 :(得分:2)
您的期望并非毫无根据。
这里有两种力量在起作用:
这两个中的哪一个首先失败是任何猜测,并且高度依赖于JVM的设置。将-Xmx设置为一个非常低的值,你很可能首先得到一个OOMException。
答案 2 :(得分:1)
因为它进入一个无限循环,其中Person构造函数再次调用构造函数。
堆栈有一个限制,当它到达错误时。
http://docs.oracle.com/javase/6/docs/api/java/lang/StackOverflowError.html
答案 3 :(得分:0)
原因是在Person()的默认构造函数中发生了递归调用。
在更深层次的JVM知识中解释这个问题:java虚拟机规范已经排除了java堆栈的两种异常情况:
也许可以帮到你:)。