http://download.forge.objectweb.org/ (asm下载的父级目录)
http://download.forge.objectweb.org/asm/ (asm各个版本的下载地址)
http://download.forge.objectweb.org/eclipse-update/ (asm的eclipse插件)
http://andrei.gmxhome.de/bytecode/ (asm eclipse plugin在线安装及使用)
http://andrei.gmxhome.de/eclipse/ (asm eclipse plugin在线安装地址)
笔者在这里略微修改了asm官方例子中的Hello World代码。
下面的代码需要引用asm-5.0.2.jar和asm-commons-5.0.2.jar两个jar包。
Helloworld.java代码如下:
package com.shihuan.test; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.GeneratorAdapter; import org.objectweb.asm.commons.Method; public class Helloworld extends ClassLoader implements Opcodes { /** * @param args * @throws IOException * @throws SecurityException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static void main(String[] args) throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException { // Generates the bytecode corresponding to the following Java class: // // public class Example { // public static void main (String[] args) { // System.out.println("Hello world!"); // } // } // creates a ClassWriter for the Example public class, // which inherits from Object ClassWriter cw = new ClassWriter(0); cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "com/shihuan/test/MyExample", null, "java/lang/Object", null); // creates a MethodWriter for the (implicit) constructor MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); // pushes the 'this' variable mw.visitVarInsn(Opcodes.ALOAD, 0); // invokes the super class constructor mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mw.visitInsn(Opcodes.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(Opcodes.ACC_PUBLIC+Opcodes.ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); // pushes the 'out' field (of type PrintStream) of the System class mw.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); // pushes the "Hello World!" String constant mw.visitLdcInsn("Hello world 11111!"); // invokes the 'println' method (defined in the PrintStream class) mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); mw.visitInsn(Opcodes.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:/javaworksspace/javaasm/bin/com/shihuan/test/MyExample.class"); //用文件流写文件 fos.write(code); fos.close(); Helloworld loader = new Helloworld(); Class<?> exampleClass = loader.defineClass("com.shihuan.test.MyExample", code, 0, code.length); // uses the dynamically generated class to print 'Helloworld' exampleClass.getMethods()[0].invoke(null, new Object[] { null }); // ------------------------------------------------------------------------ // Same example with a GeneratorAdapter (more convenient but slower) // ------------------------------------------------------------------------ cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "com/shihuan/test/MyExample", null, "java/lang/Object", null); // creates a GeneratorAdapter for the (implicit) constructor Method m = Method.getMethod("void <init> ()"); GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw); mg.loadThis(); mg.invokeConstructor(Type.getType(Object.class), m); mg.returnValue(); mg.endMethod(); // creates a GeneratorAdapter for the 'main' method m = Method.getMethod("void main (String[])"); mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_STATIC, m, null, null, cw); mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class)); mg.push("Hello world 22222!"); mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)")); mg.returnValue(); mg.endMethod(); cw.visitEnd(); code = cw.toByteArray(); loader = new Helloworld(); exampleClass = loader.defineClass("com.shihuan.test.MyExample", code, 0, code.length); // uses the dynamically generated class to print 'Helloworld' exampleClass.getMethods()[0].invoke(null, new Object[] { null }); } }
运行上面的代码:
Hello world 11111!
Hello world 22222!
到workspace目录下跟Helloworld.class文件同级目录会发现多了一个MyExample.class文件。