使用ASM动态创建类,可以不需要java源文件,或者在类被JAVA虚拟机装入内存之前,动态修改类。
如下,动态创建一个类Example.class并执行。
ClassWriter cw = new ClassWriter(0);
cw.visit(V1_5, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
// creates a MethodWriter for the (implicit) constructor
MethodVisitor mw = cw.visitMethod(ACC_PUBLIC,
"<init>",
"()V",
null,
null);
// pushes the 'this' variable
mw.visitVarInsn(ALOAD, 0);
// invokes the super class constructor
mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mw.visitInsn(RETURN);
// this code uses a maximum of one stack element and one local variable
mw.visitMaxs(1, 1);
mw.visitEnd();
// creates a MethodWriter for the 'main' method
mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
"main",
"([Ljava/lang/String;)V",
null,
null);
// pushes the 'out' field (of type PrintStream) of the System class
mw.visitFieldInsn(GETSTATIC,
"java/lang/System",
"out",
"Ljava/io/PrintStream;");
// pushes the "Hello World!" String constant
mw.visitLdcInsn("Hello world!");
// invokes the 'println' method (defined in the PrintStream class)
mw.visitMethodInsn(INVOKEVIRTUAL,
"java/io/PrintStream",
"println",
"(Ljava/lang/String;)V");
mw.visitInsn(RETURN);
// this code uses a maximum of two stack elements and two local
// variables
mw.visitMaxs(2, 2);
mw.visitEnd();
// gets the bytecode of the Example class, and loads it dynamically
byte[] code = cw.toByteArray();
FileOutputStream fos = new FileOutputStream("d:/com/Example.class");
fos.write(code);
fos.close();
Helloworld loader = new Helloworld();
Class<?> exampleClass = loader.defineClass("Example",code, 0, code.length);
// uses the dynamically generated class to print 'Helloworld'
exampleClass.getMethods()[0].invoke(null, new Object[] { null });
程序执行,打印“Hello world!”。
使用反编译工具查看CLASS文件,内容如下:
public class Example
{
public static void main(String[] paramArrayOfString)
{
System.out.println("Hello world!");
}
}