我正在通过ASM使用 Java 字节码,并试图让一个简单的invokedynamic
示例正常运行。我觉得好像我从根本上误解了 invokedynamic 应该如何工作。这是我迄今为止尝试过的:
在Test2.java
我有一个我希望调用的静态方法和我的引导方法:
public static int plus(int a, int b) { // method I want to dynamically invoke
return a + b;
}
public static CallSite bootstrap(MethodHandles.Lookup caller, String name,
MethodType type) throws Exception {
MethodHandle mh = MethodHandles.lookup().findStatic(Test2.class,
"plus", MethodType.methodType(int.class, int.class, int.class));
return new ConstantCallSite(mh);
}
现在,在我使用 ASM生成一个在包中Test.java
调用的类文件:Example.class
package1
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",
"([Ljava/lang/String;)V", null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
"Ljava/io/PrintStream;");
mv.visitIntInsn(BIPUSH, 42);
mv.visitIntInsn(BIPUSH, 24);
// mv.visitMethodInsn(INVOKESTATIC, "package1/Test2", "plus", "(II)I");
MethodType mt = MethodType.methodType(CallSite.class,
MethodHandles.Lookup.class, String.class, MethodType.class);
Handle bootstrap = new Handle(Opcodes.INVOKESTATIC, "package1/Test2",
"bootstrap", mt.toMethodDescriptorString());
mv.visitInvokeDynamicInsn("plus", "(II)I", bootstrap, new Object[0]);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
"(I)V");
mv.visitInsn(RETURN);
但是,当我尝试运行生成的类文件时,我收到以下信息:
线程“主”java.lang.ClassFormatError 中的异常:类文件 package1/Example 中常量池索引 23 处的错误方法句柄类型 在 java.lang.ClassLoader.defineClass1(本机方法) 在 java.lang.ClassLoader.defineClass(ClassLoader.java:792) 在 java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) 在 java.net.URLClassLoader.defineClass(URLClassLoader.java:449) 在 java.net.URLClassLoader.access$100(URLClassLoader.java:71) 在 java.net.URLClassLoader$1.run(URLClassLoader.java:361) 在 java.net.URLClassLoader$1.run(URLClassLoader.java:355) 在 java.security.AccessController.doPrivileged(本机方法) 在 java.net.URLClassLoader.findClass(URLClassLoader.java:354) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:424) 在 sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:357) 在 sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)
invokedynamic
用通常的调用(上面注释的行)替换调用invokestatic
会产生预期的结果。从错误消息来看,在我看来,Handle
代表我的引导方法 ( bootstrap
) 的格式不正确,但我不能肯定地说。任何帮助将非常感激。我正在使用 ASM 4.1。