百科问答小站 logo
百科问答小站 font logo



JVM jsr和ret指令始终理解不了?returnAddress又怎么理解呢? 第1页

  

user avatar   rednaxelafx 网友的相关建议: 
      

首先,如果题主只关心Java SE 7或更高版本的话,jsr和ret指令都可以不关心,因为Class文件从版本51(对应Java SE 7)开始就禁用这俩指令了。

Java SE 8 JVM Specification 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.)

然后,如果题主还得操心版本50或以下(对应Java SE 6或以下)的话,可以很高兴的告诉题主,Oracle/Sun JDK里的javac从JDK 1.4.2开始就不生成jsr/ret指令了,所以现实中也没啥机会遇到它们。

如果题主是在读老版本规范或者实际操作中见到了这俩指令的话,那请继续读下去。

jsr/ret这对指令的初衷是用来实现Java语言的finally语句块。

Chapter 6. The Java Virtual Machine Instruction Set
Format
jsr branchbyte1 branchbyte2

JVM规范如是说。branchbyte1和branchbyte2表示的是1个两字节参数,而不是2个参数。

The unsigned branchbyte1 and branchbyte2 are used to construct a signed 16-bit offset, where the offset is (branchbyte1 << 8) | branchbyte2.

javap或者通常用文本形式表示Java字节码时,这些带offset参数的字节码指令通常都不是把裸的offset写出来,而是把计算过后的跳转目标写出来。

在题主的例子中,

       19 jsr 24      

表示在这个方法的字节码中,偏移量19的地方的字节码指令是jsr 24,跳转目标就是位于偏移量24的字节码指令。

实际上这条jsr指令的十六进制编码是:

       A8 00 05     

0xA8是jsr指令,0x0005是跳转目标相对这条jsr指令的偏移量,所以跳转目标的地址就是19+0x0005 = 24。

jsr指令的语义,根据规范是:

       ... -> ..., address     

(这种记法是什么意思请参考我的另一个回答:

如何理解ByteCode、IL、汇编等底层语言与上层语言的对应关系? - RednaxelaFX 的回答

也就是说,jsr指令执行完之后,JVM会把控制跳转到指定的偏移量上,同时会把紧接在这条jsr指令之后的字节码指令的地址压到操作数栈顶。

在题主给的例子里,位于偏移量24的字节码指令马上把操作数栈顶的returnAddress保存了下来(到局部变量2),最后的ret则从局部变量2找到returnAddress跳转回到刚才那条jsr指令之后的地方继续执行。

那么为啥需要这个returnAddress?这是因为同一个finally语句块可以被一个try块和多个catch块共用,例如:

       try {   // ... } catch (SomeException se) {   // ... } catch (SomeOtherException soe) {   // ... } finally {   // ... }     

这个finally块就被一个try块两个catch块共用,它们在末尾都会用jsr“调用”这个finally块,然后要“返回”到原本的代码继续向后执行。如果不使用returnAddress就无法判断一个finally块执行完之后要“返回”到哪里去了。

(千万注意这里的“调用”“返回”都是把finally块当作一个迷你例程看待,不是Java语言层面的方法调用与方法返回。)

前面说了,Sun JDK 1.4.2之后的javac就不生成jsr/ret指令了。那finally块要如何实现?

javac采用的办法是把finally块的内容复制到原本每个jsr指令所在的地方。这样就不需要jsr/ret了,代价则是字节码大小会膨胀…




  

相关话题

  为什么 Java 份额那么高,在知乎的存在感却不如 Python? 
  如何看待哔哩哔哩用Go语言重写所有的Java后台工程? 
  怎么避免写Java风格的Scala代码? 
  精通 Java 是一种怎样的体验? 
  创业公司选择 .NET 技术栈究竟比选 Java/Python 贵多少钱? 
  求助,大一学Java还是C#? 
  eclipse强转无法输出ASCII码为3的字符(黑桃),而输出unicode值可以? 
  Java 不能实现真正泛型的原因是什么? 
  你什么时候对 Java 感到绝望? 
  准备校招JAVA开发,求推荐几本的书? 

前一个讨论
人体湿气,体内湿气这种提法科学吗?人体酸碱性已经被证明是个伪命题,是不科学的提法了,那这个呢?
下一个讨论
java中,堆的运行速度为什么比栈慢?





© 2024-11-09 - tinynew.org. All Rights Reserved.
© 2024-11-09 - tinynew.org. 保留所有权利