为什么 (int)MethodHandle.invokeExact 缺少 checkcast-instruction?

Why checkcast-instruction is absent for (int)MethodHandle.invokeExact?

我已经为 try Java 创建了 2 个简单的 classes MethodHandle-API:

public class Foo {
    private static int staticField;

    public static Object getStaticField() {
        return staticField;
    }
}

另一个 class 以两种方式调用方法 Foo.getStaticField() - 直接和使用 MethodHandle-API:

....
public static void methodHandleGetStaticField() throws Throwable {
    MethodHandle methodHandle = lookup.findStatic(Foo.class, "getStaticField", MethodType.methodType(int.class));
    int i = (int)methodHandle.invokeExact();
}

public static void directGetStaticField() {
    int i = (int)Foo.getStaticField();
}
....

我已经反编译了 class 并看到 directGetStaticField 方法包含转换指令 a,但是方法 methodHandleGetStaticField 没有,尽管 java.lang.invoke.MethodHandle.invokeExact() returns java.lang.Object.

public static void directGetStaticField();
descriptor: ()V
Code:
   0: invokestatic  #70    // Method ru/fj/methodhandle/Foo.getStaticField:()Ljava/lang/Object;
   3: checkcast     #33    // class java/lang/Integer
   6: invokevirtual #74    // Method java/lang/Integer.intValue:()I
   9: istore_0
  10: return

public static void methodHandleGetStaticField() throws java.lang.Throwable;
descriptor: ()V
Code:
   0: getstatic     #15    // Field lookup:Ljava/lang/invoke/MethodHandles$Lookup;
   3: ldc           #29    // class ru/fj/methodhandle/Foo
   5: ldc           #90    // String getStaticField
   7: getstatic     #32    // Field java/lang/Integer.TYPE:Ljava/lang/Class;
  10: invokestatic  #38    // Method java/lang/invoke/MethodType.methodType:(Ljava/lang/Class;)Ljava/lang/invoke/MethodType;
  13: invokevirtual #46    // Method java/lang/invoke/MethodHandles$Lookup.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
  16: astore_0
  17: aload_0
  18: invokevirtual #52    // Method java/lang/invoke/MethodHandle.invokeExact:()I
  21: istore_1
  22: return

谁能帮我解释一下?

您可以从其描述符 ()I:

中注意到 invokeExact 确实是 returns 一个 int
  18: invokevirtual #52    // Method java/lang/invoke/MethodHandle.invokeExact:()I

因此,不需要转换。

之所以 returns 是 int,而不是 Object,是因为 invokeExact(以及 invoke)在 MethodHandle被特殊对待,见invokeExact API

Returns:

the signature-polymorphic result, statically represented using Object

并且来自 signature polymorphism

... The unusual part is that the symbolic type descriptor is derived from the actual argument and return types, not from the method declaration.