Java字节码

http://asm.ow2.org/index.html  (asm官方网址)
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文件。

猜你喜欢

转载自shihuan830619.iteye.com/blog/2067894