1.实体类
package com.study.asm;
public class Person {
private String name;
public void sayName(){
System.out.println(name);
}
}
2.Client
package com.study.asm;
import java.io.File;
import java.io.FileOutputStream;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
public class GenerateNewPerson {
public static void main(String[] args) throws Exception{
// 使用全限定名,创建一个ClassReader对象
ClassReader classReader = new ClassReader("com.study.asm.Person");
// 构建一个ClassWriter对象,并设置让系统自动计算栈和本地变量大小
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassAdapter classAdapter = new GeneralClassAdapter(classWriter);
classReader.accept(classAdapter, ClassReader.SKIP_DEBUG);
byte[] classFile = classWriter.toByteArray();
File file = new File("D://Person.class");
FileOutputStream fos = new FileOutputStream(file);
fos.write(classFile);
fos.close();
}
}
class GeneralClassAdapter extends ClassAdapter{
public GeneralClassAdapter(ClassVisitor cv) {
super(cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
// 当是sayName方法是做对应的修改
if(name.equals("sayName")){
MethodVisitor newMv = new sayNameMethodAdapter(mv);
return newMv;
}else{
return mv;
}
}
// 定义一个自己的方法访问类
class sayNameMethodAdapter extends MethodAdapter{
public sayNameMethodAdapter(MethodVisitor mv) {
super(mv);
}
// 在源方法前去修改方法内容,这部分的修改将加载源方法的字节码之前
@Override
public void visitCode() {
// 记载隐含的this对象,这是每个JAVA方法都有的
mv.visitVarInsn(Opcodes.ALOAD, 0);
// 从常量池中加载“yy”字符到栈顶
mv.visitLdcInsn("yy");
// 将栈顶的"yy"赋值给name属性
mv.visitFieldInsn(Opcodes.PUTFIELD, Type.getInternalName(Person.class), "name", Type.getDescriptor(String.class));
}
}
}
3.结果
通过jd-gui反编译后,得到的结果如下:
package com.study.asm;
import java.io.PrintStream;
public class Person
{
private String name;
public void sayName()
{
this.name = "yy";
System.out.println(this.name);
}
}
通过javap -c Person命令,得到如下结果:
public class com.study.asm.Person extends java.lang.Object{
public com.study.asm.Person();
Code:
0: aload_0
1: invokespecial #10; //Method java/lang/Object."<init>":()V
4: return
public void sayName();
Code:
0: aload_0
1: ldc #13; //String yy
3: putfield #15; //Field name:Ljava/lang/String;
6: getstatic #21; //Field java/lang/System.out:Ljava/io/PrintStream;
9: aload_0
10: getfield #15; //Field name:Ljava/lang/String;
13: invokevirtual #27; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
16: return
}