1

当一个方法被调用时,JVM 知道为它分配多少空间。

但如果我有这样的代码:

while(someCondition) {
   Path p = someMethodThatReturnsAPath();
    //do some things
}

堆栈上发生了什么?这是发生了什么吗?:

  • 列出它在堆栈上创建一个指向的指针(指向从方法返回的 Path 的指针)
  • 有些事情已经完成
  • p,或“指向 Path 对象的指针的指针”从堆栈中删除
  • 重复

上面的代码与以下代码之间是否存在任何(即使很小)性能差异:

Path p = null;
while(someCondition) {
    p = someMethodThatReturnsAPath();
    //do some things
}
4

2 回答 2

1

这取决于。如果您关闭 Hotspot,那么性能可能会存在很小的差异,并且事情的运行方式几乎与您在上面所期望的方式相同。随着 Hotspot 的参与,现代 JVM 通常使用一组分层的编译器来动态优化代码。通常 JVM 开始解释,然后在方法的多次迭代(包括方法中的循环)之后,该方法将在后台线程中进行优化,并在某个点与解释版本交换出来。然后在其他触发器上可能会发生更多优化,或者由于新信息而必须恢复。您可能会发现,如果 JVM 可以证明它不起作用并且没有副作用,那么对循环中的方法的调用会完全消失,或者循环可能会展开。

判断发生了什么的一个好方法是添加一些 JVM 标志。以下标志将告诉您何时优化方法 -XX:+PrintCompilation(并在此处记录https://gist.github.com/rednaxelafx/1165804#file_notes.md)和 -XX:+UnlockDiagnosticVMOptions -XX:+ PrintAssembly 将为您提供在 C1 和 C2 编译器启动时生成的汇编代码。

于 2013-04-11T17:59:50.157 回答
0

方法所需的所有堆栈都在进入该方法时分配,并在离开时释放。查看生成的字节码。没有对应于进入或离开内部块的字节码指令。局部变量的字节码只是按编号引用现有的堆栈槽。

因此,指针根本不会“从堆栈中移除”。堆栈槽可能会被内部块范围之外的后续声明重用:这是另一回事。

请注意,与其他答案和评论相反,HotSpot 不会在任何地方出现。HotSpot 无法优化不存在的指令。(但是,它可以消除确实存在的代码。)

于 2013-04-11T23:42:16.223 回答