Proj. THUIoTFuzz: Java库-ASM#2

Generics

为了向后兼容,关于泛型的信息并不是直接存在type或者method descriptors中的,而是存在type, method和class signatures中。而这些signatures是存在class/field/method declarations中的。编译器会使用这些信息做静态类型检查,不过编译的时候不会使用这些信息,具体运行的时候也是使用type casts或者reflection来实现的。

Type signature

基本规则如下:

示例:

Method Signature

示例:

Class Signature

SignatureVisitor

执行顺序

基本方法还是SignatureReader->SignatureVisitor->SignatureWriter

例子


Annotation

如果Annotation的retention policy不是RetentionPolicy.Source,那么annotations都会存在compiled class中,可以通过reflection API获取。
Annotations在源代码中可能有多种形式,比如@Deprecated,或者@Retention(RetentionPolicy.CLASS)等。不过,几乎所有的annotations是以一个annotation type开头,后面跟着一串name value对,而value只能是: 1. primitive, Class, String
2. enum
3. annotation values//annotation能够嵌套其他的annotation
4. arrays of the above values

AnnotationVisitor


执行顺序

例子-删除annotation

很简单,在ClassVisitor执行visitAnnotation返回null即可。

例子-添加annotation

所有的在visitAnnotation之后的方法都需要重载来确认确实添加了Annotation。

Debug

使用javac -g编译出来的classes会包含调试信息,主要就是包含sourcefile的名称,line numbers等。
ASM提供了visitSource, visitLineNumber, visitLocalVariable(获取具体variable names)

Tree API

ClassNode是ClassVisitor的一种,不过通过ClassNode有机会非线性访问数据。

基本使用模式

  ClassReader classReader = new ClassReader(source);
  ClassNode classNode = new ClassNode();
  classReader.accept(classNode, 0);
  ClassWriter classWriter = new ClassWriter(0);
  classNode.accept(classWriter);
  ClassReader classReader = new ClassReader(source);
  ClassWriter classWriter = new ClassWriter(0);
  ClassVisitor classVisitor = new ClassVisitor(ASM7, classWriter) {
    public MethodVisitor visitMethod(int access, String name,
        String desc, String signature, String[] exceptions) {
      final MethodVisitor methodVisitor = 
          super.visitMethod(access, name, desc, signature, exceptions);
      MethodNode methodNode = new MethodNode(access, name, desc, signature, exceptions) {
        public void visitEnd() {
          // transform or analyze method code using tree API
          accept(methodVisitor);
        }
      };
    }
  };
  classReader.accept(classVisitor, 0);

操作指令

第一种,线性添加

MethodNode methodNode = new MethodNode(...);
methodNode.instructions.add(new VarInsnNode(ALOAD, 0));

或者

MethodNode methodNode = new MethodNode(...);
methodNode.visitVarInsn(ALOAD, 0);

第二种,使用记录下来的AbstractInsnNode来添加

MethodNode methodNode = new MethodNode(...);
methodNode.visitVarInsn(ALOAD, 0);
AbstractInsnNode ptr = methodNode.instructions.getLast();
methodNode.visitVarInsn(ALOAD, 1);
// inserts an instruction between ALOAD 0 and ALOAD 1
methodNode.instructions.insert(ptr, new VarInsnNode(ALOAD, 0));
...
原文地址:https://www.cnblogs.com/xuesu/p/14136567.html