对于 Java 函数中的语句:
Xxx xxx = new Xxx() {
public Abc abc(final Writer out) {
return new SomeFunction(out) {
boolean isDone = false;
public void start(final String name) {
/* blah blah blah */
}
};
}
};
哪些变量(包括函数)放在堆上,哪些将放在堆栈上?
我问这个问题的原因是 JVM 中的段错误:
kernel: java[14209]: segfault at 00002aab04685ff8 rip 00002aaab308e4d0 rsp 00002aab04685ff0 error 6
00002aab04685ff8
和00002aab04685ff0
很近,看来栈增长太快了。我尝试调查这部分代码,怀疑是否是多次调用该函数时出现问题的原因。有没有可能是堆上的一些变量引用了栈没有清空?
最佳答案
关于特定对象是否进入堆的问题有点牵扯。
一般来说,在Java中,所有的对象都分配在堆上,因为一个方法可能会返回或存储一个指向对象的指针。如果该对象已被放入堆栈,则下次将堆栈帧放在那里时它会被覆盖。
但是,HotSpot JIT 编译器会做一些叫做 Escape Analysis 的事情.该分析通过查看方法的代码来查明对象是否“脱离”了方法的范围。如果一个对象没有转义,编译器可以安全地将它分配到堆栈上。
维基百科有一些关于 Escape Analysis in Java 的更多信息,也关于多线程和锁定。
关于堆栈溢出:调用堆栈上的堆栈帧总是在方法完成后被删除。实际上,甚至不需要明确删除它。下一帧将覆盖之前的内容。
此外,尽管在其他语言(如 C)中,将非常大的对象放入堆栈可能会导致堆栈溢出,但我认为这不会在 Java 中发生。我希望 Sun(Oracle)的工程师足够聪明,不会让 VM 在堆栈上存储巨大的对象。
所以出现栈溢出的唯一可能是嵌套方法调用过多。由于堆栈空间足够大,可以处理任何“正常”方法调用嵌套,因此堆栈溢出通常表示代码中存在无限(或非常大的)递归。
关于java - Java中,哪些对象放在栈上,哪些放在堆上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10481528/