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

时间:2016-06-27 16:04:47

标签: java jvm stack

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

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

enter image description here

如您所见,调用者中的操作数堆栈成为被调用者帧中的args。 在被调用者框架中,会出现" junk"在我恢复保存的寄存器之前需要清理的操作数堆栈上的(返回值除外)?

3 个答案:

答案 0 :(得分:2)

请参阅return的文档:

  

操作数堆栈

     

......→[空]

     

描述

     

...如果没有抛出异常,则丢弃当前帧(第2.6节)的操作数堆栈上的任何值。

分别为

ireturn

  

操作数堆栈

     

...,值→[空]

     

描述

     

...如果没有抛出异常,则从当前帧(第2.6节)的操作数堆栈中弹出值,并将其推送到调用者帧的操作数堆栈。当前方法的操作数堆栈上的任何其他值都将被丢弃。

我认为,这提供了足够的提示,即操作数堆栈上可能存在必须被“丢弃”的值,但是,在典型的实现中,不需要采取任何操作,因为丢弃堆栈帧整体意味着丢弃操作数叠加。

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

答案 1 :(得分:1)

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

  

每个帧(第2.6节)包含一个称为的后进先出(LIFO)堆栈   它的操作数堆栈。

和框架创建/销毁corresponds to方法调用/完成

  

每次调用方法时都会创建一个新帧。一个框架是   在方法调用完成时销毁,无论是否   完成是正常的或突然的(它会引发未被捕获的异常)。

当方法返回时,这并没有给出关于操作数堆栈的深刻见解,但至少它回答了关于清理操作数堆栈的需要的问题:因为它是帧本地的,所以不需要清理 - 因为操作数堆栈与其帧一起被丢弃。

答案 2 :(得分:0)

这个问题很难确切地回答,因为你没有准确说明你所询问的内容。

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

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

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