技术开发 频道

探秘Java 7:JVM动态语言支持详解

  请看 invokevirtual 一行,它调用了一个方法,而不是对操作对象栈进行操作。从该行注释,我们可以看到,它指出了以下信息:

  ◆提供方法的接收器(receiver)类:java.io.PrintStream

  ◆方法名称:println

  ◆方法参数类型:(I) 表示 Integer

  ◆方法返回值: V 表示 void

  这些信息相当于方法的签名。JVM 查找具有该签名的方法,在这里,就是 java.io.PrintStream 类中的 println:(I)V.如果该方法不在那个类中,JVM 将在类的子类中继续查找。

  满足要求所进行的拙劣尝试

  为了让动态类型语言满足字节码对方法调用的要求,已经有了多种尝试,但没有一种是理想的。

  以下面的代码为例:

  function max (x,y) {
  
if x.lessThan(y) then y else x
  }

 

  接收器和参数都没有指定类型,而对于动态类型语言,直到运行时才提供类型信息,因此,以上代码未能满足方法调用需提前获悉类型的要求,也就不能在 Java 平台上成功地编译为字节码。

  问题的解决方法之一是为返回值和方法参数创建虚假的(synthetic)Java 类型。在这里,虚假表示非真实存在。例如,动态类型语言在实现是可能将代码更改为:

  Interface50 function max (Interface 51 x,Interface52 y) {
  
if x.lessThan(y) then y else x
  }

 

  类型 Interface 51 和 Interface52 并不存在,只是为了满足相应的要求而指定。

  另一种方法成为映射调用(relfected invocation),使用 java.lang.reflect.Method 对象调用方法,而避开直接调用方法。这样也就绕开了指定类型的要求。

  第三种方法是为动态语言的实现创建一个独特的方法调用解释器(interpreter),以运行在 JVM 上。

  虚假类型满足了 Java 字节码的要求。但这种方法不但繁复而且会带来问题。如果动态语言引擎需要更改,相应的实现器(implementer)必须重新创建虚假 Java 类型,这种操作常会出错。

  运行调用也有其自身的局限。例如,java.lang.reflect.Method 对象提供了动态语言所需的方法访问,但对象必须是运行时可用的特定 Java 类型。虽然,动态语言可以在运行期间提供类型信息,但不是都可以通过用户映射的规范 Java 类型。

  JSR 292 —— 动态语言支持的下一步

  JSR 292 为 JVM 引入了一个新的 Java 字节码指令,invokedynamic,以及一个新的方法连接机制。

  方法调用的字节码指令

  Java 虚拟机规范指定了 4 个字节码,用于方法调用:

  ◆invokevirtual

  ◆invokeinterface

  ◆invokestatic

  ◆invokespecial

0
相关文章