Status of JSR/RET in JVM spec

2019-04-22 04:07发布

问题:

There are some parts of the JVM specification which suggest that the operations JSR (Jump SubRoutine), JSR_W (Jump SubRoutine Wide) and RET (RETurn from subroutine) may be used only up to class file version 50.0 (JDK 1.6):

3.13 Compiling Finally

(This section assumes a compiler generates class files with version number 50.0 or below, so that the jsr instruction may be used. See also §4.10.2.5.)

And later:

4.10.2.5. Exceptions and finally

To implement the try-finally construct, a compiler for the Java programming language that generates class files with version number 50.0 or below may use the exception-handling facilities together with two special instructions: jsr ("jump to subroutine") and ret ("return from subroutine").

On the other hand, the opcode descriptions themselves say nothing about a deprecation of these features. And the quoted texts only say how things used to be in versions up to 50.0, but doesn't explicitely state the state of affairs after that.

This comment (to a question which asks about the motivation behind this deprecation or removal) indicates a similar level of confusion, so apparently I'm not the only one looking for this.

回答1:

While adding links to my question, I noticed that the opcodes in question are absent from §4.10.1.9: Type Checking Instructions. So this shows that the new strackframe-based type verification scheme can't handle them, and §4.10: Verification of class Files writes:

Verification by type checking must be used to verify class files whose version number is greater than or equal to 50.0.

Or in more detail in §4.10.1: Verification by Type Checking:

A class file whose version number is 50.0 or above (§4.1) must be verified using the type checking rules given in this section.

If, and only if, a class file's version number equals 50.0, then if the type checking fails, a Java Virtual Machine implementation may choose to attempt to perform verification by type inference (§4.10.2).

So I'd say a version 50.0 class may still contain jsr and ret, but runs some risk that a JVM implementation won't verify said class and as a consequence will fail loading it.

But then I found an even more explicit rule, in §4.9.1: Static Constraints:

Only instances of the instructions documented in §6.5 may appear in the code array. Instances of instructions using the reserved opcodes (§6.2) or any opcodes not documented in this specification must not appear in the code array.

If the class file version number is 51.0 or above, then neither the jsr opcode or the jsr_w opcode may appear in the code array.

The first paragraph is irrelevant for this question, since the instructions are listed in §6.5, and are not reserved according to §6.2. But the second paragraph explicitely marks them as forbidden in version 51.0 and up. The ret opcode, on the other hand, is useless without jsr or jsr_w, since only these two instructions can create a stack element of type returnAddress (and via some astore a local variable of that type) to by used by ret.


I still think that some notice to this effect should have been included in §6.5. Unfortunately, the Java bug report webpage hides the Continue button if one selects Type: Bug, Category: Java Platform Standard Edition, Subcategory: specification. It states that

This subcategory is for reporting technical errors and ambiguities in the text of the Java Language Specification and the JVM Specification. It is not the venue to propose new features in the Java language or JVM. Ongoing feature development is carried out in OpenJDK; corresponding enhancements to the Java Language Specification and the JVM Specification are managed through the Java Community Process.

But going through the JCP just to get some clarifying notes added to the descriptions of these three opcodes feels like massive overkill. So I hope that this post here helps those who on their own fail to find an answer in the specification itself.