对于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 */
}
};
}
};
Run Code Online (Sandbox Code Playgroud)
哪个变量(包括函数)放在堆上,哪些变量放在堆栈上?
我问这个的原因是JVM中的分段错误:
kernel: java[14209]: segfault at 00002aab04685ff8 rip 00002aaab308e4d0 rsp 00002aab04685ff0 error 6
Run Code Online (Sandbox Code Playgroud)
00002aab04685ff8并且00002aab04685ff0附近,似乎堆栈增长太快.我尝试研究这部分代码,并怀疑它是多次调用此函数时是否是问题的原因.如果堆被堆上的某些变量引用,堆栈是否可能被清除?
关于特定对象是否在堆上的问题有点涉及.
通常,在Java中,所有对象都在堆上分配,因为方法可以在某处返回或存储指向对象的指针.如果对象已经放在堆栈上,那么下次堆栈框架放在那里时就会覆盖它.
但是,HotSpot JIT编译器会执行一个名为Escape Analysis的操作.此分析通过查看其实现来查明对象是否"逃避"该方法的范围.如果对象没有转义,编译器可以安全地在堆栈上分配它.
维基百科有关于Java中的Escape Analysis的更多信息,还有关于多线程和锁定的信息.
关于堆栈溢出:在方法完成后,总是删除调用堆栈上的堆栈帧.实际上,甚至没有必要明确删除它.下一帧将覆盖以前的帧.
此外,虽然在其他语言(如C)中,可能通过在堆栈上放置非常大的对象来导致堆栈溢出,但我认为这不会发生在Java中.我希望Sun(Oracle)的工程师足够聪明,不要让VM在堆栈中存储大量对象.
因此,堆栈溢出的唯一可能性是具有太多嵌套方法调用.由于堆栈空间非常大,足以处理任何"普通"方法调用嵌套,因此堆栈溢出通常意味着代码中的无限(或非常大)递归.