天天看點

Java 位元組碼操控架構ASM(三):修改 classes

Account.java

package com.asm.modifyclass;

/**
 * Created by ouer1994 on 2017/2/18.
 */
public class Account {
    public static void main(String args[]) {
        new Account().doAccount();
    }

    public void doAccount() {
        System.out.println("Account doAccount ... ");
    }
}
           

Generator.java

package com.asm.modifyclass;

import org.objectweb.asm.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by ouer1994 on 2017/2/18.
 */
public class Generator {
    public static void main(String args[]) {
        try {
            ClassReader classReader = new ClassReader("com/asm/modifyclass/Account");
            ClassWriter classWriter = new ClassWriter(0);
            ClassVisitor classVisitor = new MyClassAdapter(classWriter, "main", "([Ljava/lang/String;)V");
            classReader.accept(classVisitor, 0);

            byte[] data = classWriter.toByteArray();
            File file = new File("Account.class");
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(data);
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class MyClassAdapter extends ClassVisitor {

        private String mDesc;
        private String methodName;

        public MyClassAdapter(ClassVisitor cv, String methodName, String mDesc) {
            super(Opcodes.ASM4, cv);
            this.mDesc = mDesc;
            this.methodName = methodName;
        }


        @Override
        public MethodVisitor visitMethod(int i, String s, String s1, String s2, String[] strings) {
            // 删除方法
            if (s.equals(methodName) && s1.equals(mDesc)) {
                return null;
            }
            // 修改方法的權限修飾符
            return cv.visitMethod(Opcodes.ACC_PRIVATE, s, s1, s2, strings);
        }
    }

}
           

為類增加字段

AddFieldAdapter.java

package com.asm.addingclassmembers;

import org.objectweb.asm.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by ouer1994 on 2017/2/21.
 */
public class AddFieldAdapter extends ClassVisitor {

    private String fName;
    private int fAcc;
    private String fDesc;
    private boolean isFieldPresent;

    public AddFieldAdapter(ClassVisitor classVisitor, int fAcc, String fDesc, String fName) {
        super(Opcodes.ASM4, classVisitor);
        this.fAcc = fAcc;
        this.fDesc = fDesc;
        this.fName = fName;
    }

    public static void main(String args[]) {
        try {
            ClassReader classReader = new ClassReader("com/asm/modifyclass/Account");
            ClassWriter classWriter = new ClassWriter(0);
            ClassVisitor classVisitor = new AddFieldAdapter(classWriter, Opcodes.ACC_PRIVATE, "I", "added");
            classReader.accept(classVisitor, 0);

            byte[] data = classWriter.toByteArray();
            File file = new File("Account.class");
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(data);
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    @Override
    public FieldVisitor visitField(int i, String s, String s1, String s2, Object o) {
        if (s.equals(fName)) {
            isFieldPresent = true;
        }
        return super.visitField(i, s, s1, s2, o);
    }

    @Override
    public void visitEnd() {
        super.visitEnd();
        if (!isFieldPresent) {
            FieldVisitor fieldVisitor = cv.visitField(fAcc, fName, fDesc, null, null);
            if (fieldVisitor != null) {
                fieldVisitor.visitEnd();
            }

        }
        cv.visitEnd();
    }
}
           

繼續閱讀