ASM笔记

作者: 大冷月 | 来源:发表于2022-06-12 10:50 被阅读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(局部变量编号)

    相关文章

      网友评论

          本文标题:ASM笔记

          本文链接:https://www.haomeiwen.com/subject/jpzimrtx.html