Java字节码删除或者添加一个类方法

以下代码需要asm-5.0.2.jar和asm-commons-5.0.2.jar两个包。

package com.shihuan.method;

public class AccountMethod {

	String sql = "select * from tables";

	public AccountMethod() {
		
	}
	
	public AccountMethod(String sql) {
		super();
		this.sql = sql;
	}

	public void operation() {
        System.out.println("shihuan operation...");
    }
	
	int executeInternal() {
		
		System.out.println("shihuan executeInternal...");
		
		if (true) {
			System.out.println(this.sql);
			return 2;
		}
		
		return 3;
	}
	
}


package com.shihuan.method;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
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 AsmAddMethod {

	public static void main(String[] args) throws IOException {
		
		ClassReader cr = new ClassReader("com.shihuan.method.AccountMethod");
        ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
        ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw){};
        cr.accept(cv, Opcodes.ASM5);
        
      //新增加一个方法
        MethodVisitor mw= cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC,
                "add",
                "([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("this is add method print!");
        // 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(0, 0);
        mw.visitEnd();
        
		byte[] code = cw.toByteArray();
		OutputStream fos = new FileOutputStream("D:/myworkspace/JavaAsm/bin/com/shihuan/method/AccountMethod.class");
		fos.write(code);
		fos.close();

	}

}


package com.shihuan.method;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class AsmDeleteMethod {

	public static void main(String[] args) throws IOException {
		ClassReader cr = new ClassReader("com.shihuan.method.AccountMethod");
		ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
		ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) {
			
			public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
				if("executeInternal".equals(name)) {
		            return null;
		        }
				return super.visitMethod(access, name, desc, signature, exceptions); //不为null,保留
		    }
			
		};
		cr.accept(cv, ClassReader.SKIP_DEBUG);

		byte[] code = cw.toByteArray();
		OutputStream fos = new FileOutputStream("D:/myworkspace/JavaAsm/bin/com/shihuan/method/AccountMethod.class");
		fos.write(code);
		fos.close();
	}

}


AsmAddMethod2.java这种方式会清空掉AccountMethod.java文件中的所有内容,然后加入新方法,一般用的情况比较少。
package com.shihuan.method;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;

public class AsmAddMethod2 {

	public static void main(String[] args) throws IOException {

		ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
		cw.visit(38, Opcodes.ACC_PUBLIC, "com.shihuan.method.AccountMethod", null, "java/lang/Object", null);
		Method m = Method.getMethod("void <init> ()");
		GeneratorAdapter ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC, m, null, null, cw);
		ga.loadThis();
		ga.invokeConstructor(Type.getType(Object.class), m);
		ga.returnValue();
		ga.endMethod();

		m = Method.getMethod("void doSomething()");
		ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC, m, null, null, cw);
		ga.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
		ga.push("动态生成,动态加载调用方法");
		ga.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println(String)"));
		ga.returnValue();
		ga.endMethod();

		byte[] code = cw.toByteArray();
		OutputStream fos = new FileOutputStream("D:/myworkspace/JavaAsm/bin/com/shihuan/method/AccountMethod.class");
		fos.write(code);
		fos.close();

	}

}

猜你喜欢

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