4

我有这个类,我编译它。

package org.test;

import java.util.function.Supplier;

public class Test {
    static String get() { return "!!"; }

    public static void main(String[] args) {
        Supplier<String> sup = Test::get;
        System.out.println(sup.get());
    }
}

然后,试图查看它的字节码,我得到以下public static void main函数的开头:

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: invokedynamic #3,  0              // InvokeDynamic #0:get:()Ljava/util/function/Supplier;
         5: astore_1
         6: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;

在这里,我们可以看到 invokedynamic 调用,如果我理解正确的话,它会创建 Supplier 接口的匿名实例。传递给invokedynamic 的是两个参数,一个是#3。第二个参数是 0。所以,我的第一个问题是:这里的 0 代表什么?

在常量池中,#3 代表#3 = InvokeDynamic #0:#27 // #0:get:()Ljava/util/function/Supplier;. 常量池中有对#27 的引用,但没有对#0 的引用。我的第二个问题是:#0 在这里代表什么?

4

1 回答 1

6

#0您可以在invokedynamic 旁边的注释中看到)实际上是BootstrapMethods表中的一个索引。所以第一个问题,0其实是指#0. 而这又是 BootstrapMethods 表的索引。它提供了invokedynamic调用来源和目标方法之间的链接。

如果你反编译,javap -c -v FileName你会看到整个常量池。(我假设你已经完成了?)。在这里您应该找到对#X MethodHandle #y:#z IDDL.bootstrapDynamic. 这就是 BootstrapMethods 表链接到的点。链接到的句柄#0最终应该解析为一个static bootstrapDynamic()方法。

于 2016-07-28T09:51:20.953 回答