gpt4 book ai didi

java - 使用 ASM 生成有效的 invokedynamic 指令

转载 作者:搜寻专家 更新时间:2023-10-31 20:12:28 25 4
gpt4 key购买 nike

我正在通过 ASM 使用 Java 字节码并试图让一个简单的 invokedynamic 示例正常运行。我觉得好像我从根本上误解了 invokedynamic 应该如何工作。到目前为止,这是我尝试过的:

Test2.java 中,我有一个我希望调用的静态方法和我的 Bootstrap 方法:

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);
}

现在,在 Test.java 中,我使用 ASM 在 package1 包中生成一个名为 Example.class 的类文件:

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);

但是,当我尝试运行生成的类文件时,我收到以下信息:

Exception in thread "main" java.lang.ClassFormatError: Bad method handle kind at constant pool index 23 in class file package1/Example    at java.lang.ClassLoader.defineClass1(Native Method)    at java.lang.ClassLoader.defineClass(ClassLoader.java:792)    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)    at java.security.AccessController.doPrivileged(Native Method)    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)

invokedynamic 调用替换为通常的 invokestatic 调用(上面的注释行)会产生预期的结果。从错误消息看来,代表我的 Bootstrap 方法 (bootstrap) 的 Handle 格式不正确,但我不能肯定地说。任何帮助将非常感激。我正在使用 ASM 4.1。

最佳答案

您传递的是操作码而不是句柄类型作为句柄类型。由于它们都是整数,因此没有类型错误,但您提供的是垃圾值,这会在加载时导致验证错误。

你可能打算做这样的事情(注意 H_ 前缀)

Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "package1/Test2",
"bootstrap", mt.toMethodDescriptorString());

参见 here用于处理文档。

关于java - 使用 ASM 生成有效的 invokedynamic 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18971830/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com