asm-giude阅读笔记004(ASM核心API接口和对应组件---生成字节码)

2.2.3 生成类

 

生成类只需要用到ClassWriter这个组件。

 

先看一个例子,下面是一个接口的定义:

 

package pkg

 

public interface Comparable extends Mesurable {

   

    int LESS = -1;

    int EQUAL = 0;

    int GREATER = 1;

    int compareTo(Object o);

 

}

 

上面这个接口的生成可以通过调用ClassVisitor的6个方法来完成:

 

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;

 

public class GenerateInterface {
 
    public static void main(String[] args) {


        ClassWriter cw = new ClassWriter(0);


        cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT + Opcodes.ACC_INTERFACE,
                "pkg/Comparable", null, "java/lang/Object", new String[] { "java/lang/Cloneable" });


        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "LESS", "I",
                null, new Integer(-1)).visitEnd();


        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "EQUAL", "I",
                null, new Integer(0)).visitEnd();


        cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "GREATER", "I",
                null, new Integer(1)).visitEnd();


        cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "compareTo",
                "(Ljava/lang/Object;)I", null, null).visitEnd();


        cw.visitEnd();


        byte[] bs = cw.toByteArray();

 

    }

 

}

 

cw.visit(...)方法调用的解释:

 

    Opcodes.V1_5:指明要生成的字节码的版本为Java1.5。

 

    Opcodes.ACC_XXX:对应Java修饰符。

 

    "pkg/Comparable":指明了当前接口的内部名字。

 

    null:指明了当前接口的泛型,由于这个接口没有泛型化,所以这里这个参数为null。

 

    "java/lang/Object":当前接口的父类。

 

    new String[] { "pkg/Mesurable" }:当前接口的所有父接口。

 

cw.visitField(...):

 

    Opcodes.ACC_XXX:对应Java修饰符。

 

    "LESS":字段的名字。

 

    "I":字段的类型。

 

    null:泛型,字段没有使用泛型,因此为null。

 

    new Integer(-1):该字段的常量值。

 

cw.visitMethod(...):

 

    Opcodes.ACC_XXX:对应Java修饰符。

 

    "compareTo":方法名。


    "(Ljava/lang/Object;)I":该方法的方法描述符。

   

    null:泛型,由于方法没有使用泛型,所以为null。

 

    null:方法声明抛出的所有异常类型,由于没有声明抛出任何异常,所以为null。

 

使用刚才生成的类:

 

刚才生成的类的字节码保存在了一个byte数组中,我们先自定义一个ClassLoader,然后使用这个ClassLoader将刚才生成的类加载到内存中:

 

public class MyClassLoader extends ClassLoader {

    public Class defineClass(String name, byte[] bs) {

        return defineClass(name, bs, 0, bs.length);

    }

}

 

刚才生成的类可以被我们自定义的类加载器直接加载:

 

byte[] bs = ...

ClassLoader classLoader = new MyClassLoader();

Class class = classLoader.defineClass("pkg.Comparable", bs);

 

你可能感兴趣的:(asm-giude阅读笔记004(ASM核心API接口和对应组件---生成字节码))