【问题标题】:How do I get and use a class type from a Java class that I've dynamically created at runtime using ASM?如何从使用 ASM 在运行时动态创建的 Java 类中获取和使用类类型?
【发布时间】:2013-04-21 20:53:48
【问题描述】:

我想扩展类,获取类文字,将其用作类型参数,或强制转换为它。

我已经有了解决方法,但我仍然很好奇。

目前我可以在运行时使用 ASM 定义一个类,创建一个 Object 类型的实例并通过反射调用其方法,但我不知道如何将其用作类类型。

当然,编译器不知道在运行时定义的类,但在这种情况下我知道它,我认为我看到它隐藏在 ASMified .java 文件中(下面的示例)。如何让编译器相信它实际上确实在编译时知道类类型?

感谢观看,

-朱利安

ASMified B 类示例:欺骗class B{String hello = "Hello B!"} 的字节码生成代码:

import java.util.*;
import org.objectweb.asm.*;
//import org.objectweb.asm.attrs.*;
public class BDump implements Opcodes {

public static byte[] dump () throws Exception {

ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;

cw.visit(V1_6, ACC_SUPER, "B", null, "java/lang/Object", null);

{
fv = cw.visitField(0, "hello", "Ljava/lang/String;", null, null);
fv.visitEnd();
}
{
mv = cw.visitMethod(0, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn("Hello B!");
mv.visitFieldInsn(PUTFIELD, "B", "hello", "Ljava/lang/String;");
mv.visitInsn(RETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
cw.visitEnd();

return cw.toByteArray();
}
}

【问题讨论】:

    标签: java compiler-construction type-conversion metaprogramming java-bytecode-asm


    【解决方案1】:

    您不能在编译时使用在编译时不存在的类。你能做的是

    • 使用在编译时存在但在运行时替换为所需实现的类或接口。
    • 使用在编译时可用但仅在运行时实现的接口。
    • 使用反射在运行时调用构造函数/方法。

    【讨论】:

    • 感谢您的帮助。它引出了更多问题:)故障在哪里?由于在编译时没有什么我不知道该类,我天真地希望能够为编译器提供它应该期望的任何欺骗版本,但我找不到网络上的“Java Compiler For Dummies”。
    • 生成字节码是很少有十年经验的开发人员做过的事情,而几个月后您应该了解如何使用编译器的基础知识。我对您对 Java 的熟悉程度感到有些困惑。
    • 这里是菜鸟状态,通过一些有趣的项目学习Java。我知道一些关于编译器的基础知识,例如lexer/scanner-parser-analyzer 阶段,但我似乎无法找出 exactly AST 的使用方式以及每个阶段发生的情况 exactly 以便我能够规避任何引发错误的检查。
    猜你喜欢
    • 1970-01-01
    • 2015-06-29
    • 2010-11-14
    • 2023-02-23
    • 2011-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多