我是靠谱客的博主 小巧店员,最近开发中收集的这篇文章主要介绍ASM动态操作方法(增改),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

下面基于4.2版本的一个使用示例,演示了对类Foo进行修改方法名称,增加方法,修改方法内容等

package myASM;

public class Foo {
	public  void execute(){
		System.out.println("test changed method name");
	}
	
	public  void changeMethodContent(){
		System.out.println("test changed method");
	}
}

 

package myASM;

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

public class MethodChangeClassAdapter extends ClassVisitor implements Opcodes{
	public MethodChangeClassAdapter(ClassVisitor cv) {
		super(Opcodes.ASM4, cv);
	}
	
	@Override
	public void visit(int version, int access, String name, String signature,
            String superName, String[] interfaces) {
        if (cv != null) {
            cv.visit(version, access, name, signature, superName, interfaces);
        }
    }
	
	@Override
    public MethodVisitor visitMethod(int access, String name, String desc,
            String signature, String[] exceptions) {
		//当方法名为execute时,修改方法名为execute1
        if (cv != null && "execute".equals(name)){
            return cv.visitMethod(access, name + "1", desc, signature, exceptions);
        }
        
        //此处的changeMethodContent即为需要修改的方法  ,修改方法內容
        if("changeMethodContent".equals(name)){
        	//先得到原始的方法
        	MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
        	MethodVisitor newMethod = null;
        	//访问需要修改的方法
        	newMethod = new AsmMethodVisit(mv); 
        	return newMethod;
        }
        if (cv != null) {  
            return cv.visitMethod(access, name, desc, signature, exceptions);  
        }
        return null;
    }
}

 

package myASM;

import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class AsmMethodVisit extends MethodVisitor{
	public AsmMethodVisit(MethodVisitor mv) {
		super(Opcodes.ASM4, mv);
	}
	
	@Override
    public void visitMethodInsn(int opcode, String owner, String name,
            String desc) {
    	super.visitMethodInsn(opcode, owner, name, desc); 
    }
	
	@Override
	public void visitCode(){
		//此方法在访问方法的头部时被访问到,仅被访问一次  
        //此处可插入新的指令  
        super.visitCode();
	}
	
	@Override
	public void visitInsn(int opcode){
		//此方法可以获取方法中每一条指令的操作类型,被访问多次  
        //如应在方法结尾处添加新指令,则应判断:
		if(opcode == Opcodes.RETURN){
			// pushes the 'out' field (of type PrintStream) of the System class 
			mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
			// pushes the "Hello World!" String constant 
			mv.visitLdcInsn("this is a modify method!");
			 // invokes the 'println' method (defined in the PrintStream class) 
			mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
		}
		super.visitInsn(opcode);
	}
}

 

package myASM;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

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 AsmExample extends ClassLoader implements Opcodes{

	public static void main(String args[]) throws IOException, IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, InstantiationException{
		ClassReader cr = new ClassReader(Foo.class.getName());
		ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
		ClassVisitor cv = new MethodChangeClassAdapter(cw);
		cr.accept(cv, Opcodes.ASM4);
		
		//新增加一个方法
		MethodVisitor mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "add", "([Ljava/lang/String;)V", null, null);
		mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
		mw.visitLdcInsn("this is add method print!");
		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(0, 0);
		mw.visitEnd();
		
		byte[] code = cw.toByteArray();
		AsmExample loader = new AsmExample();
		Class<?> exampleClass = loader.defineClass(Foo.class.getName(), code, 0, code.length);
		
		for(Method method : exampleClass.getMethods()){
			System.out.println(method);
		}
		
		System.out.println("***************************");
		
		// uses the dynamically generated class to print 'Helloworld'
		//調用changeMethodContent,修改方法內容
		exampleClass.getMethods()[1].invoke(exampleClass.newInstance(), null);
		
		System.out.println("***************************");
		//調用execute,修改方法名 
		exampleClass.getMethods()[2].invoke(exampleClass.newInstance(), null); 
		// gets the bytecode of the Example class, and loads it dynamically  
		  
        FileOutputStream fos = new FileOutputStream("e:\logs\Example.class");  
        fos.write(code);  
        fos.close();
 	}
	
}

 最后在eclipse控制台输出结果:

 

public static void myASM.Foo.add(java.lang.String[])
public void myASM.Foo.changeMethodContent()
public void myASM.Foo.execute1()
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
***************************
test changed method
this is a modify method!
***************************
test changed method name

 

然后通过反编译软件,查看E盘生成的Example.class

 

package myASM;

import java.io.PrintStream;

public class Foo
{

    public Foo()
    {
    }

    public void execute1()
    {
        System.out.println("test changed method name");
    }

    public void changeMethodContent()
    {
        System.out.println("test changed method");
        System.out.println("this is a modify method!");
    }

    public static void add(String as[])
    {
        System.out.println("this is add method print!");
    }
}

 

最后

以上就是小巧店员为你收集整理的ASM动态操作方法(增改)的全部内容,希望文章能够帮你解决ASM动态操作方法(增改)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部