美文网首页
ASM简介(三)

ASM简介(三)

作者: 千里山南 | 来源:发表于2016-07-29 17:22 被阅读405次

使用修改类

如果我们一次性修改的类比较多,如果想使用这些类,我们可以使用java.lang.instrument.ClassFileTransformer

public static void premain(String agentArgs, Instrumentation inst) {
    inst.addTransformer(new ClassFileTransformer() {
        public byte[] transform(ClassLoader l, String name, Class c, ProtectionDomain d, byte[] b) throws IllegalClassFormatException {
            ClassReader cr = new ClassReader(b);
            ClassWriter cw = new ClassWriter(cr, 0);
            ClassVisitor cv = new ChangeVersionAdapter(cw);
            cr.accept(cv, 0);
            return cw.toByteArray();
        }
    });
}
  • 删除类的相关成员
    对于删除内部及外部类,我们可以在相关visit函数中不调用super方法即可。对于函数和成员变量我们需要在visit方法中返回null
  • 添加成员
    我们只需调用ClassWriter的相关visit方法即可添加对应的成员
    我们不能在visitSource visitOuterClass cisitAnnnotation或者visitAttribute之后添加visitField。我们只能在visitInnerClass visitField visitMethod或者visitEnd方法后调用visitField
    不过一般来说,我们更倾向于在visitEnd后添加相应的visit函数。
    我们在添加相关成员时一般倾向于选择类似_counter$或者4B7F来避免重名。
  • 链式转换
    对于复杂的修改或者翻译,我们可以使用链式的修改模式。我们可以在一个ClassVisitor中将其中的visitor方法分发到很多个ClassVisitor中,当然也可以将多个Visitor的消息派发到同一个ClassVisitor中。

一些工具类

  • Type, Type提供了Class对象和其内部描述相转换的方法。Type.getType(String.class).getDescriptor()方法返回"Ljava/lang/String"。Type也可用于描述方法,可以使用方法描述符或者Method对象来初始化Type对象。Type的getArgumentTypes 和 getReturnType 可以用于获取方法的参数类型及返回值类型。

  • TraceClassVisitor 对于转换后的class可以提供更好的可读性

    ClassWriter cw = new ClassWriter(0);
    TraceClassVisitor cv = new TraceClassVisitor(cw, printWriter);
    cv.visit(...);...cv.visitEnd();
    byte b[] = cw.toByteArray();
    

其打印结果如下:

// class version 49.0 (49) // access flags 1537 
public abstract interface pkg/Comparable implements pkg/Mesurable{ // access flags 25 
    public final static I LESS = -1 // access flags 25
    public final static I EQUAL = 0 // access flags 25 
    public final static I GREATER = 1 // access flags 1025
    public abstract compareTo(Ljava / lang / Object;)I
}
  • CheckClassAdapter 由于ClassWriter对visit的调用并不会进行check,因此有可能会生成根本无法运行的class。对此我们可以使用CheckClassAdapter来进行校验,如果调用时机不对,其会抛出相关异常。使用方法类似TraceClassVisitor

  • ASMIfier 该类能在访问对应的方法的时候生成对应的生成改类的ASM代码。ASMifier也可以通过控制台来使用:java -classpath asm.jar:asm-util.jar \ org.objectweb.asm.util.ASMifier \ java.lang.Runnable 会生成如下代码:

      package asm.java.lang;import org.objectweb.asm.*;
      public class RunnableDump implements Opcodes {
      public static byte[] dump() throws Exception {
          ClassWriter cw = new ClassWriter(0);
          FieldVisitor fv;
          MethodVisitor mv;
          AnnotationVisitor av0;
          cw.visit(V1_5, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, "java/lang/Runnable", null, "java/lang/Object", null);
          {
              mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "run", "()V", null, null);
              mv.visitEnd();
          }
          cw.visitEnd();
          return cw.toByteArray();
      }
    }

相关文章

  • ASM简介(三)

    使用修改类 如果我们一次性修改的类比较多,如果想使用这些类,我们可以使用java.lang.instrument....

  • ASM 简介

    前言 很早之前就写过面向切面的编程思想,主要学习了AOP的思想(参考:AOP简介)以及使用 AspectJ 实现简...

  • ASM简介(一)

    之前简单研究过ASM这个字节码修改框架,最近要用到,故简单复习下。顺便翻译下官方文档(翻译主要是给自己看的,因此比...

  • ASM简介(二)

    访问class 访问一个class的最简单的方式是声明一个ClassReader类,然后复写其中的方法。Class...

  • ASM简介(四)

    函数 我们在使用ASM相关API对函数进行操作之前,我们需要了解函数在字节码的存储格式及其执行模型。 执行模型 我...

  • ASM简介(六)

    TreeAPI Class ASM中修改生成class主要依赖ClassNode类 生成class时我们只需构造对...

  • ASM简介(五)

    元数据 泛型 泛型在运行时并不会被字节码指令使用,但可以被反射API拿到,可以被编译器使用。由于向前兼容的原因,泛...

  • 工具开发,字节码技术

    简介 几个对比: https://segmentfault.com/a/1190000009956534ASM(A...

  • Android编译时技术04 --- ASM

    部分内容来自:https://www.jianshu.com/p/29e9b03c0796 一.ASM简介 ASM...

  • ASM Core Api 详解

    前言 前面一篇文章 ASM 简介 对 ASM 框架做了简单的介绍。 本篇文章主要对该框架的 Core Api 其中...

网友评论

      本文标题:ASM简介(三)

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