ASM筆記

1. 準備工作

idea安裝插件:ASM ByteCode Outline,用于將class生成ASM相關代碼,供參考使用。寫好代碼,Build編譯后,在類上面右鍵Show Bytecode Outline
jadx:用于反編譯修改好的class,看是否修改成功

2. ClassVisitor文檔備注(待完善)

ClassVisitor 類的方法必須按以下順序調(diào)用(在這個類的 Javadoc 中規(guī)定):
visit visitSource? visitOuterClass? ( visitAnnotation | visitAttribute )* 
(visitInnerClass | visitField | visitMethod )* 
visitEnd

這意味著必須首先調(diào)用 visit,
然后是對 visitSource 的最多一個調(diào)用,
接下來是對visitOuterClass的最多一個調(diào)用,
然后是可按任意順序?qū)?visitAnnotation 和visitAttribute 的任意多個訪問,
接下來是可按任意順序?qū)?visitInnerClass、visitField 和 visitMethod 的任意多個調(diào)用,
最后以一個 visitEnd 調(diào)用結束。

//待完善
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 

這就意味著,對于非抽象方法,如果存在注釋和屬性的話,必須首先訪問它們,
然后是該方法的字節(jié)代碼。
對于這些方法,其代碼必須按順序訪問,
位于對 visitCode 的調(diào)用(有且僅有一個調(diào)用)與對 visitMaxs 的調(diào)用(有且僅有一個調(diào)用)之間。


//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;"
指令轉(zhuǎn)換為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); 創(chuàng)建一個long型的局部變量,
返回值是varIndex(局部變量編號)
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 任何一臺計算機的指令系統(tǒng)一般都包含有幾十條到上百條指令,下面按一般計算機的功能把指令劃分以下幾種類型.(1)算術運...
    onedam閱讀 1,729評論 0 0
  • 更多內(nèi)容請查看個人博客codercc[https://www.codercc.com] 1. 方法監(jiān)控背景 在日常...
    你聽___閱讀 1,028評論 1 2
  • 一、概念 1.1 無符號數(shù): 以 u1、u2、u3、u4、u8 代表 1 個字節(jié),2 個字節(jié)、4 個字節(jié)、8 個字...
    JiaJianHuang閱讀 336評論 0 0
  • 在前面的文章中,我們分析了Class 這個字節(jié)碼文件的格式,知道了字節(jié)碼的作用,那么我們就可以直接生成字節(jié)碼文件,...
    wo883721閱讀 1,502評論 0 2
  • 一、Class 文件結構初識 “與平臺無關” 的理想最終實現(xiàn)在操作系統(tǒng)的應用層面上:眾多虛擬機廠商發(fā)布了許多可以運...
    凱玲之戀閱讀 1,029評論 0 1

友情鏈接更多精彩內(nèi)容