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/
访问原文「方法句柄」获取最佳阅读体验并参与讨论