public class Foo { private static void bar(Object o) { } private static MethodHandles.Lookup lookup() { // Lookup的创建位置,具备Foo类的访问权限 return MethodHandles.lookup(); } public static void main(String[] args) throws Exception { // 获取方法句柄的不同方式 MethodHandles.Lookup lookup = Foo.lookup(); Method method = Foo.class.getDeclaredMethod("bar", Object.class); MethodHandle mh0 = lookup.unreflect(method); MethodType t = MethodType.methodType(void.class, Object.class); MethodHandle mh1 = lookup.findStatic(Foo.class, "bar", t); } }
// 严格匹配参数类型 public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable; // 自动适配参数类型 public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable;
public void test(MethodHandle handle, String s) throws Throwable { handle.invokeExact(s); handle.invokeExact((Object) s); }
public void test(java.lang.invoke.MethodHandle, java.lang.String) throws java.lang.Throwable; descriptor: (Ljava/lang/invoke/MethodHandle;Ljava/lang/String;)V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=3 0: aload_1 1: aload_2 // 传入的参数为String,对应的方法描述符为String 2: invokevirtual // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;)V 5: aload_1 6: aload_2 // 转化为Object,对应的方法描述符为Object 7: invokevirtual // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/Object;)V 10: return
invoke会调用 MethodHandle asType(MethodType)
方法
MethodHandle asType(MethodType)
MethodHandles.dropArguments
MethodHandle bindTo(Object)
// -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames -> 打印隐藏的栈信息 // -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true -> 导出class文件 public class A { private static void bar(Object o) { new Exception().printStackTrace(); } public static void main(String[] args) throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodType methodType = MethodType.methodType(void.class, Object.class); MethodHandle methodHandle = lookup.findStatic(A.class, "bar", methodType); methodHandle.invokeExact(new Object()); } }
java.lang.Exception at me.zhongmingmao.basic.method_handle.A.bar(A.java:11) at java.lang.invoke.LambdaForm$DMH001/746292446.invokeStatic_001_L_V(LambdaForm$DMH001:1000010) at java.lang.invoke.LambdaForm$MH012/468121027.invokeExact_000_MT(LambdaForm$MH012:1000016) at me.zhongmingmao.basic.method_handle.A.main(A.java:18)
JVM对invokeExact调用做了特殊处理,会调用到一个 共享的,与方法句柄类型相关的特殊适配器 中,该适配器是一个 LambdaForm
$ javap -v -p -c LambdaForm/$MH012 static void invokeExact_000_MT(java.lang.Object, java.lang.Object, java.lang.Object); descriptor: (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V flags: ACC_STATIC Code: stack=2, locals=3, args_size=3 0: aload_0 1: aload_2 // 检验参数类型 2: invokestatic // Method java/lang/invoke/Invokers.checkExactType:(Ljava/lang/Object;Ljava/lang/Object;)V 5: aload_0 // -Djava.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD=127 // checkCustomized:是否为为该方法句柄生成一个特有的适配器 6: invokestatic // Method java/lang/invoke/Invokers.checkCustomized:(Ljava/lang/Object;)V 9: aload_0 10: checkcast // class java/lang/invoke/MethodHandle 13: dup 14: astore_0 15: aload_1 // JVM同样会对invokeBasic做特殊处理,将会调用至方法句柄本身所持有的适配器中,该适配器同样是LambdaForm 16: invokevirtual // Method java/lang/invoke/MethodHandle.invokeBasic:(Ljava/lang/Object;)V 19: return
$ javap -v -p -c LambdaForm/$DMH001 static void invokeStatic_001_L_V(java.lang.Object, java.lang.Object); descriptor: (Ljava/lang/Object;Ljava/lang/Object;)V flags: ACC_STATIC Code: stack=2, locals=3, args_size=2 0: aload_0 1: invokestatic #16 // Method java/lang/invoke/DirectMethodHandle.internalMemberName:(Ljava/lang/Object;)Ljava/lang/Object; 4: astore_2 5: aload_1 6: aload_2 7: checkcast #18 // class java/lang/invoke/MemberName // JVM会对linkToStatic调用做特殊处理, // 将根据传入的MemberName参数所存储的方法地址或者方法表索引,直接跳转到目标方法 10: invokestatic #24 // Method java/lang/invoke/MethodHandle.linkToStatic:(Ljava/lang/Object;Ljava/lang/invoke/MemberName;)V 13: return
转载请注明出处:http://zhongmingmao.me/2018/12/23/jvm-basic-method-handle/
访问原文「方法句柄」获取最佳阅读体验并参与讨论