JVM规范中的JSR / RET状态

时间:2016-05-03 20:28:00

标签: java jvm opcode finally jvm-bytecode

JVM规范的某些部分建议操作JSR (Jump SubRoutine)JSR_W (Jump SubRoutine Wide)RET (RETurn from subroutine)仅可用于类文件版本50.0(JDK 1.6):

  

3.13 Compiling Finally

     

(本节假设编译器生成版本号为50.0或更低版本的类文件,以便可以使用jsr指令。另请参阅§4.10.2.5。)

后来:

  

4.10.2.5. Exceptions and finally

     

要实现try - finally构造,用于生成版本号为50.0或更低版本的class文件的Java编程语言的编译器可以使用异常处理工具和两个特殊说明: jsr (“跳转到子程序”)和 ret (“从子程序返回”)。

另一方面,操作码描述本身并未说明这些功能的弃用。引用的文本只说明过去50.0版本中的事情是如何产生的,但在此之后并没有明确说明事态。

This comment(关于这个弃用或删除背后的动机的问题)表明存在类似的混乱程度,所以显然我不是唯一一个寻找这种混淆的人。

1 个答案:

答案 0 :(得分:10)

在添加我的问题的链接时,我注意到§4.10.1.9: Type Checking Instructions中没有相关的操作码。所以这表明新的基于strackframe的类型验证方案无法处理它们,§4.10: Verification of class Files写道:

  

必须使用类型检查进行验证,以验证版本号大于或等于50.0的class个文件。

§4.10.1: Verification by Type Checking中的更详细信息:

  

版本号为50.0或更高版本(§4.1)的class文件必须使用本节中给出的类型检查规则进行验证。

     

当且仅当class文件的版本号等于50.0时,如果类型检查失败,Java虚拟机实现可以选择尝试通过类型推断(§4.10.2)执行验证

所以我说版本50.0类可能仍然包含 jsr ret ,但是存在JVM实现赢得的一些风险'验证所说的课程,结果加载失败。

但后来我在§4.9.1: Static Constraints中找到了更明确的规则:

  

只有§6.5中记录的说明实例可能会出现在code数组中。使用保留的操作码(§6.2)或本规范中未记录的任何操作码的指令实例不得出现在code数组中。

     

如果class文件版本号为51.0或更高,那么 jsr 操作码或 jsr_w 操作码都不会出现在code中阵列。

第一段与此问题无关,因为说明书在§6.5中列出,并未根据§6.2保留。但第二段显然标志着它们在51.0及更高版本中被禁止。另一方面, ret 操作码在没有 jsr jsr_w 的情况下是无用的,因为只有这两个指令才能创建类型为{的堆栈元素 ret 使用{1}}(并通过某些 astore 该类型的局部变量)。

我仍然认为应该在§6.5中包含一些关于这种效果的注意事项。不幸的是,Java bug report webpage会隐藏继续按钮,如果选择类型:错误,类别: Java平台标准版,子类别:< EM>规范。它说明了

  

此子类别用于报告Java语言规范和JVM规范文本中的技术错误和含糊之处。它不是在Java语言或JVM中提出新功能的场所。正在进行的功能开发在OpenJDK中进行;通过Java Community Process管理Java语言规范和JVM规范的相应增强功能。

但是通过JCP只是为了在这三个操作码的描述中添加一些澄清的注释,感觉就像是大规模的过度杀伤。所以我希望这篇文章可以帮助那些自己无法在规范中找到答案的人。