用ASM生成工作invokedynamic指令

我正在通过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);
}

现在,在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)

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


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

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

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

在这里查看Handle文档。

链接地址: http://www.djcxy.com/p/33055.html

上一篇: Generating working invokedynamic instruction with ASM

下一篇: Netty (4.0.4) version compress/decompress string messages error