【问题标题】:What happens on the stack during a loop? [duplicate]循环期间堆栈上会发生什么? [复制]
【发布时间】:2013-04-04 00:56:29
【问题描述】:

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

但如果我有这样的代码:

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

堆栈上发生了什么? 这是怎么回事?:

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

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

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

【问题讨论】:

  • 您忘记了优化器。

标签: java stack


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 只是想知道.. 会不会慢一些?它必须为每个循环的指针找到一个新的堆栈槽?
    猜你喜欢
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    • 2019-10-06
    • 2015-07-10
    相关资源
    最近更新 更多