[英]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
There are three problems with your code. 您的代码有三个问题。
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). 虽然这看似正确,但实际上你想要传递它
0
( Opcodes.NULL
意味着不同的东西)。
ClassWriter cw=new ClassWriter(0);
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);
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.