ASM笔记

2022-06-12  本文已影响0人  大冷月

1. 准备工作

idea安装插件:ASM ByteCode Outline,用于将class生成ASM相关代码,供参考使用。写好代码,Build编译后,在类上面右键Show Bytecode Outline
jadx:用于反编译修改好的class,看是否修改成功

2. ClassVisitor文档备注(待完善)

ClassVisitor 类的方法必须按以下顺序调用(在这个类的 Javadoc 中规定):
visit visitSource? visitOuterClass? ( visitAnnotation | visitAttribute )* 
(visitInnerClass | visitField | visitMethod )* 
visitEnd

这意味着必须首先调用 visit,
然后是对 visitSource 的最多一个调用,
接下来是对visitOuterClass的最多一个调用,
然后是可按任意顺序对 visitAnnotation 和visitAttribute 的任意多个访问,
接下来是可按任意顺序对 visitInnerClass、visitField 和 visitMethod 的任意多个调用,
最后以一个 visitEnd 调用结束。

//待完善
public abstract class ClassVisitor {

    /**
     * 
     * @param api
     */
    public ClassVisitor(int api) {}

    /**
     * 
     * @param api
     * @param cv
     */
    public ClassVisitor(int api, ClassVisitor cv) {}

    /**
     * 
     * @param version
     * @param access
     * @param name
     * @param signature
     * @param superName
     * @param interfaces
     */
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {}

    /**
     * 
     * @param source
     * @param debug
     */
    public void visitSource(String source, String debug){}

    /**
     * 
     * @param owner
     * @param name
     * @param desc
     */
    public void visitOuterClass(String owner, String name, String desc){}

    /**
     * 
     * @param desc
     * @param visible
     * @return
     */
    AnnotationVisitor visitAnnotation(String desc, boolean visible){}

    /**
     * 
     * @param attr
     */
    public void visitAttribute(Attribute attr){}

    /**
     * 
     * @param name
     * @param outerName
     * @param innerName
     * @param access
     */
    public void visitInnerClass(String name, String outerName, String innerName, int access){}

    /**
     * 
     * @param access
     * @param name
     * @param desc
     * @param signature
     * @param value
     * @return
     */
    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value){}

    /**
     * 
     * @param access
     * @param name
     * @param desc
     * @param signature
     * @param exceptions
     * @return
     */
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions){}

    /**
     * 
     */
    void visitEnd(){}
}

3. MethodVisitor文档备注

visitAnnotationDefault? 
( visitAnnotation | visitParameterAnnotation | visitAttribute )* 
( visitCode 
 ( visitTryCatchBlock | visitLabel | visitFrame | visitXxxInsn | 
 visitLocalVariable | visitLineNumber )* 
 visitMaxs )? 
visitEnd 

这就意味着,对于非抽象方法,如果存在注释和属性的话,必须首先访问它们,
然后是该方法的字节代码。
对于这些方法,其代码必须按顺序访问,
位于对 visitCode 的调用(有且仅有一个调用)与对 visitMaxs 的调用(有且仅有一个调用)之间。


//MethodVisitor备忘文档,待完善
abstract class MethodVisitor {

    /**
     * 
     * @param api
     */
    MethodVisitor(int api);

    /**
     * 
     * @param api
     * @param mv
     */
    MethodVisitor(int api, MethodVisitor mv);

    /**
     * 
     * @return
     */
    AnnotationVisitor visitAnnotationDefault();

    /**
     * 
     * @param desc
     * @param visible
     * @return
     */
    AnnotationVisitor visitAnnotation(String desc, boolean visible);

    /**
     * 
     * @param parameter
     * @param desc
     * @param visible
     * @return
     */
    AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible);

    /**
     * 
     * @param attr
     */
    void visitAttribute(Attribute attr);

    /**
     * 
     */
    void visitCode();

    /**
     * 
     * @param type
     * @param nLocal
     * @param local
     * @param nStack
     * @param stack
     */
    void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack);

    /**
     * 
     * @param opcode
     */
    void visitInsn(int opcode);

    /**
     * 
     * @param opcode
     * @param operand
     */
    void visitIntInsn(int opcode, int operand);

    /**
     * 
     * @param opcode
     * @param var
     */
    void visitVarInsn(int opcode, int var);

    /**
     * 
     * @param opcode
     * @param desc
     */
    void visitTypeInsn(int opcode, String desc);

    /**
     * 
     * @param opc
     * @param owner
     * @param name
     * @param desc
     */
    void visitFieldInsn(int opc, String owner, String name, String desc);

    /**
     * 
     * @param opc
     * @param owner
     * @param name
     * @param desc
     */
    void visitMethodInsn(int opc, String owner, String name, String desc);

    /**
     * 
     * @param name
     * @param desc
     * @param bsm
     * @param bsmArgs
     */
    void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs);

    /**
     * 
     * @param opcode
     * @param label
     */
    void visitJumpInsn(int opcode, Label label);

    /**
     * 
     * @param label
     */
    void visitLabel(Label label);

    /**
     * 
     * @param cst
     */
    void visitLdcInsn(Object cst);

    /**
     * 
     * @param var
     * @param increment
     */
    void visitIincInsn(int var, int increment);

    /**
     * 
     * @param min
     * @param max
     * @param dflt
     * @param labels
     */
    void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels);

    /**
     * 
     * @param dflt
     * @param keys
     * @param labels
     */
    void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels);

    /**
     * 
     * @param desc
     * @param dims
     */
    void visitMultiANewArrayInsn(String desc, int dims);

    /**
     * 
     * @param start
     * @param end
     * @param handler
     * @param type
     */
    void visitTryCatchBlock(Label start, Label end, Label handler, String type);

    /**
     * 
     * @param name
     * @param desc
     * @param signature
     * @param start
     * @param end
     * @param index
     */
    void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index);

    /**
     * 
     * @param line
     * @param start
     */
    void visitLineNumber(int line, Label start);

    /**
     * 
     * @param maxStack
     * @param maxLocals
     */
    void visitMaxs(int maxStack, int maxLocals);

    /**
     * 
     */
    void visitEnd();
}
字段名 格式 备注
owner "java/lang/System"
name "out"
descriptor "Ljava/io/PrintStream;"
指令转换为ASM代码解释
指令 ASM方法 备注
LDC mv.visitLdcInsn("字符串")
ALOAD 0
ASTORE 1
ICONST_0
ICONST_3
ALOAD 1
ILOAD 2
ASTORE 3
int x = newLocal(Type.LONG_TYPE); 创建一个long型的局部变量,
返回值是varIndex(局部变量编号)
上一篇下一篇

猜你喜欢

热点阅读