Java字节码调用接口指令

Java字节码调用接口指令,java,jvm,Java,Jvm,在Eclipse类文件查看器中查看这个Java字节码时,我注意到invokeinterface指令有一点奇怪:它有一个nargs数量的参数“attribute”,占据2个字节: 35 aload_2 [map] 36 ldc <String "a"> [15] 38 invokeinterface java.util.Map.get(java.lang.Object) : java.lang.Object [33] [nargs: 2] 43 checkcast java.l

在Eclipse类文件查看器中查看这个Java字节码时,我注意到invokeinterface指令有一点奇怪:它有一个nargs数量的参数“attribute”,占据2个字节:

35  aload_2 [map]
36  ldc <String "a"> [15]
38  invokeinterface java.util.Map.get(java.lang.Object) : java.lang.Object [33] [nargs: 2]
43  checkcast java.lang.String [35]
46  invokevirtual java.io.PrintStream.println(java.lang.Object) : void [47]
49  getstatic java.lang.System.out : java.io.PrintStream [41]

为什么会存在这种情况?invokeinterface和invokevirtual之间有什么区别?JVM不应该推断参数的数量,从而从给定的方法签名中从堆栈中弹出的值的数量吗?

可以从签名中推断参数的数量,这是正确的。政府必须这样说:


invokeinterface指令的计数操作数记录参数值数量的度量值,其中long或double类型的参数值为计数值提供两个单位,而任何其他类型的参数提供一个单位。此信息也可以从所选方法的描述符中派生。冗余是历史性的。

可以从签名推断参数的数量,这是对的。政府必须这样说:


invokeinterface指令的计数操作数记录参数值数量的度量值,其中long或double类型的参数值为计数值提供两个单位,而任何其他类型的参数提供一个单位。此信息也可以从所选方法的描述符中派生。裁员是历史性的。

比我强多了。我不知道为什么第一个JVM规范中就已经有了这种方法描述符,我敢肯定,这似乎对原始JVM的优化都没有帮助。如果你知道该去哪里看的话,规范中隐藏着各种奇怪的和历史性的东西。碰巧的是,在InvokedDynamic的一些早期实验中,这些残留字段派上了用场。我不知道为什么第一个JVM规范中就已经有了这种方法描述符,我敢肯定,这似乎对原始JVM的优化都没有帮助。如果你知道该去哪里看的话,规范中隐藏着各种奇怪的和历史性的东西。碰巧的是,在invokedynamic的一些早期实验中,这些残留字段非常有用