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 には 2 つの引数が渡され、そのうちの 1 つは #3 です。2 番目の引数は 0 です。最初の質問は、0 は何を表しているのでしょうか?

定数プールでは #3 は を表します#3 = InvokeDynamic #0:#27 // #0:get:()Ljava/util/function/Supplier;。定数プールに #27 への参照がありますが、#0 への参照はありません。2 番目の質問は、#0 は何を表しているのでしょうか?

4

1 に答える 1

6

( #0invokedynamic の横のコメントで確認できます) は、実際には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 に答える