简体   繁体   English

Java ASM需要帮助

[英]Java ASM help need

I write a simple program using Java ASM to generate the byte code which is generated by compiling the following class. 我使用Java ASM编写一个简单的程序来生成通过编译以下类生成的字节代码。

public class Main {
    public static void main(String[] args) {
        System.out.println("Test");
    }
}

The code I wrote to generate the bytecode for this class is given below. 我编写的用于生成此类的字节码的代码如下所示。

public class CodeGenerator {

    public void generateClass()
    {
        ClassWriter cw=new ClassWriter(Opcodes.NULL);
        FieldVisitor fv;
        MethodVisitor mv;
        cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Main", null, "java/lang/Object", null);
        mv=cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitVarInsn(Opcodes.AALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
        mv=cw.visitMethod(Opcodes.ACC_PUBLIC+ Opcodes.ACC_STATIC, "Main", "([Ljava/lang/String;)V", null, null);
        mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream");
        mv.visitLdcInsn("Test");
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(2, 1);
        mv.visitEnd();
        cw.visitEnd();
        this.WriteClass(cw);
    }
    public void WriteClass(ClassWriter cw){
        FileOutputStream fos;
        try{
            fos = new FileOutputStream("E:\\Acadamic\\Final year project\\ASM\\Main.class");
            fos.write(cw.toByteArray());
            fos.close();
        }
        catch (IOException ex){
            Logger.getLogger(CodeGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

This compiles successfully and when I try to run it, it gives the following error. 这成功编译,当我尝试运行它时,它会出现以下错误。

Exception in thread "main" java.lang.NoClassDefFoundError: main/class
Caused by: java.lang.ClassNotFoundException: main.class
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: main.class.  Program will exit.

can any one please help me for avoid this error. 任何人都可以帮助我避免这个错误。 If anyone can explain the cause to the error and how to avoid it, please be kind enough to help me. 如果有人能够解释错误的原因以及如何避免错误,请善待我。

Thank You. 谢谢。

Follow-up: 跟进:

When I run it like java Main it gives the following error. 当我像java Main一样运行它时会出现以下错误。

Exception in thread "main" java.lang.ClassFormatError: Field "out" in class Main
 has illegal signature "Ljava/io/PrintStream"
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(Unknown Source)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$000(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: Main.  Program will exit.

I don't think your error is being caused by ASM. 我不认为您的错误是由ASM引起的。 It looks like you simply called java incorrectly. 看起来你只是错误地调用了java You should call it like this: 你应该这样称呼它:

java Main

My guess is that you called it like this: 我猜你是这样叫的:

java Main.class

Update 更新

There are three problems with your code. 您的代码有三个问题。

Problem #1 问题#1

The ClassWriter constructor accepts a bit mask of options. ClassWriter构造函数接受选项的位掩码。 You passed it Opcodes.NULL . 你传递了它Opcodes.NULL Although this may seem correct, you actually want to pass it 0 ( Opcodes.NULL means something different). 虽然这看似正确,但实际上你想要传递它0Opcodes.NULL意味着不同的东西)。

ClassWriter cw=new ClassWriter(0);

Problem #2 问题#2

You are calling AALOAD in the constructor instead of ALOAD . 您在构造函数中调用AALOAD而不是ALOAD The AALOAD instruction loads an array element , whereas ALOAD loads a local variable . AALOAD指令加载数组元素 ,而ALOAD加载局部变量

mv.visitVarInsn(Opcodes.ALOAD, 0);

Problem #3 问题#3

In your Main method, you forgot the semicolon after Ljava/io/PrintStream : 在您的Main方法中,您忘记了Ljava/io/PrintStream之后的分号:

mv.visitFieldInsn(
    Opcodes.GETSTATIC,
    "java/lang/System",
    "out",
    "Ljava/io/PrintStream;" // Notice the semicolon
  );

You can save yourself some pain by taking advantage of ASM's Type class: 您可以通过利用ASM的Type类来节省一些痛苦:

mv.visitFieldInsn(
    Opcodes.GETSTATIC,
    "java/lang/System",
    "out",
    Type.getObjectType("java/io/PrintStream").getDescriptor()
  );

只是补充一点,根据经验,我发现非法签名错误通常是由于在方法描述结束时缺少分号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM