Java VM 是操作数堆栈,在方法结束时始终为空

Java VM is the operand stack always empty at end of method

在 Java VM 中,在方法结束时 returns 操作数堆栈是否仅包含 return 值(对于 void 方法为空)。或者 return 值下是否有其他值需要在堆栈中丢弃?

我正在标准 C 堆栈上创建每个方法框架。如图所示:

如您所见,调用者中的操作数堆栈成为被调用者帧中的参数。 在被调用者框架中,在我恢复我保存的寄存器之前,操作数堆栈上是否有 "junk"(除了 return 值)需要清理?

这个问题很难给出结论性的回答,因为你没有明确说明你在问什么。

规范公开可用https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf(参见第 2.6.2 章)

这表明堆栈可能处于任意状态,至少在发生未捕获的异常时是这样。我没有看到 return 值的明确提及,但由于 return 字节码被指定为 return 来自堆栈值的值,因此 必须 进入堆栈(第 3.5 章)。

规范只是描述逻辑上发生的事情。真正的 VM 不需要将规范 1:1 转换为内存布局 - 它只需要确保生成的逻辑相同(想想 JIT 代码)。

部分答案:operand stack 是框架的一部分:

Each frame (§2.6) contains a last-in-first-out (LIFO) stack known as its operand stack.

和框架creation/destructioncorresponds to方法invocation/completion

A new frame is created each time a method is invoked. A frame is destroyed when its method invocation completes, whether that completion is normal or abrupt (it throws an uncaught exception).

当一个方法 returns 时,这并没有给出关于操作数堆栈的太多信息,但至少它回答了你关于需要清理操作数堆栈的问题:因为它是帧局部的,所以有无需清理,因为操作数堆栈与其帧一起被丢弃。

参见 return 的文档:

operand stack

... → [empty]

Description

… If no exception is thrown, any values on the operand stack of the current frame (§2.6) are discarded.

ireturn,分别为:

operand stack

..., value → [empty]

Description

… If no exception is thrown, value is popped from the operand stack of the current frame (§2.6) and pushed onto the operand stack of the frame of the invoker. Any other values on the operand stack of the current method are discarded.

我认为,这给出了足够的提示,表明操作数堆栈上可能存在必须“丢弃”的值,但是,在典型的实现中,不需要任何操作,因为丢弃堆栈帧作为一个整体意味着丢弃操作数栈。

我不确定为什么这对你来说是个障碍。如果您真的想通过使用当前操作数堆栈位置到达堆栈帧的开头,您无论如何都需要有关堆栈帧的元信息,即您必须知道该帧中局部变量的数量。检索此信息并计算堆栈帧起始位置,再便宜不过了首先检索帧起始位置。