I write a simple program using Java ASM to generate the byte code which is generated by compiling the following class.
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 M开发者_JS百科ethod)
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.
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. It looks like you simply called java
incorrectly. 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
The ClassWriter
constructor accepts a bit mask of options. You passed it Opcodes.NULL
. Although this may seem correct, you actually want to pass it 0
(Opcodes.NULL
means something different).
ClassWriter cw=new ClassWriter(0);
Problem #2
You are calling AALOAD
in the constructor instead of ALOAD
. The AALOAD
instruction loads an array element, whereas ALOAD
loads a local variable.
mv.visitVarInsn(Opcodes.ALOAD, 0);
Problem #3
In your Main
method, you forgot the semicolon after 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:
mv.visitFieldInsn(
Opcodes.GETSTATIC,
"java/lang/System",
"out",
Type.getObjectType("java/io/PrintStream").getDescriptor()
);
Just to add, By experience I have found that illegal signature error generally comes due to missing semicolon at end of method description.
精彩评论