简体   繁体   English

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

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

In a Java VM, at the end of a method when it returns does the operand stack contain just the return value (or empty for void methods). 在Java VM中,方法返回时,在方法末尾,操作数堆栈仅包含返回值(对于void方法,则为空)。 Or could there be other values under the return value that need to be discarded in the stack? 还是在返回值下还有其他值需要在堆栈中丢弃?

I'm creating each methods frame on the standard C stack. 我正在标准C堆栈上创建每个方法框架。 As shown in this image: 如下图所示:

在此处输入图片说明

As you can see, the operand stack in the caller becomes the args in the callee frame. 如您所见,调用者中的操作数堆栈成为被调用者帧中的args。 In the callee frame, would there be "junk" (other than the return value) on the operand stack that needs to be cleaned up before I restore my saved registers? 在被调用方帧中,在恢复保存的寄存器之前,操作数堆栈上是否需要清除“垃圾”(返回值除外)?

See the documentation of return : 请参阅return文档:

operand stack 操作数栈

... → [empty] ...→[空]

Description 描述

… If no exception is thrown, any values on the operand stack of the current frame (§2.6) are discarded. …如果没有引发异常,则丢弃当前帧(第2.6节)的操作数堆栈上的所有值。

or ireturn , respectively: 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. …如果未引发异常,则从当前帧的操作数堆栈(第2.6节)中弹出值,并将其压入调用程序的帧的操作数堆栈。 Any other values on the operand stack of the current method are discarded. 当前方法的操作数堆栈上的任何其他值都将被丢弃。

I think, this is giving enough hints that there might be values on the operand stack that have to be “discarded”, though, in typical implementations, no action is necessary as discarding the stack frame as a whole implies discarding the operand stack. 我认为,这足以表明操作数堆栈上可能有一些值必须“丢弃”,尽管在典型的实现中,无需采取任何措施,因为丢弃整个堆栈帧意味着丢弃操作数堆栈。

I'm not sure why this is an obstacle to you. 我不确定为什么这是您的障碍。 If you really want to get the to the beginning of the stack frame by using the current operand stack position, you'll need meta information about the stack frame anyway, ie you have to know the number of local variables in that frame. 如果您确实想通过使用当前操作数堆栈位置到达堆栈帧的开头,则无论如何都将需要有关堆栈帧的元信息,即,您必须知道该帧中局部变量的数量。 Retrieving this information and calculating the stack frame start, can't be cheaper than retrieving the start of the frame in the first place. 检索这些信息并计算堆栈框架的开始,比首先检索框架的开始便宜。

A partial answer: The operand stack is part of a frame: 部分答案: 操作数堆栈是帧的一部分:

Each frame (§2.6) contains a last-in-first-out (LIFO) stack known as its operand stack. 每个帧(第2.6节)包含一个后进先出(LIFO)堆栈,称为其操作数堆栈。

and frame creation/destruction corresponds to method 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). 框架的方法调用完成时,无论该完成是正常的还是突然的(它引发未捕获的异常),它都会被销毁。

This does not give much insight about the operand stack when a method returns but at least it answers your question about the need to clean-up the operand stack: Since it is frame-local, there is no need for a clean-up since the operand stack is discarded along with its frame. 当方法返回时,这对操作数堆栈没有太多的了解,但是至少它回答了您有关需要清除操作数堆栈的问题:由于它是帧本地的,因此不需要清理。操作数堆栈及其帧将被丢弃。

The question is hard to answer conclusively, because you do not specify precisely what you're asking about. 这个问题很难下一个定论,因为您没有确切说明您要问的问题。

The specification is publically available https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf (See chapter 2.6.2) 该规范是公开可用的https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf (请参阅第2.6.2章)

This indicates that the stack may be in arbitrary state, at least when an uncaught exception occurs. 这表明至少在发生未捕获的异常时,堆栈可能处于任意状态。 I did not see an explicit mention of the return value, but since the return bytecode is specified to return a value from the stack value it must be on the stack (chapter 3.5). 我没有看到返回值的明确提及,但是由于指定了返回字节码以从堆栈值中返回一个值,因此它必须位于堆栈中(第3.5章)。

The specification is just a description what happens logically. 该规范只是逻辑上发生的描述。 A real VM does not need to translate the specification 1:1 into a memory layout - it only needs to ensure the resulting logic is identical (think of JIT'd code). 真正的VM不需要将规范1:1转换为内存布局-它只需要确保生成的逻辑是相同的即可(考虑JIT代码)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM