概述
下面基于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动态操作方法(增改)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复