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方法 | 备注 |
---|---|---|
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(局部变量编号) |
网友评论