1、什么是 ASM ?
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。
2、Java 字节码小知识
a、类型描述符
b、方法描述符
3、创建class文件
首先去官网下载一下jar包:http://forge.ow2.org/project/download.php?group_id=23&file_id=21558
接下来看代码:
package com.asm.createclass;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Created by ouer1994 on 2017/2/18.
*/
/*
package pkg;
public interface Comparable extends Mesurable {
int LESS = -1;
int EQUAL = 0;
int GREATER = 1;
int compareTo(Object o);
}
*/
public class GenerateClass {
public static void main(String args[]) {
ClassWriter classWriter = new ClassWriter(0);
// 创建类的头 public interface Comparable extends Mesurable
// param 1: Java 版本
// param 2: public abstract interface
// param 3: 全路径类名
// param 4: 泛型
// param 5: 父类,接口隐式继承自Object
// param 6: 接口数组
classWriter.visit(Opcodes.V1_8,
Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT + Opcodes.ACC_INTERFACE,
"com/asm/createclass/Comparable", null, "java/lang/Object", new String[]{"com/asm/createclass/Mesurable"});
// 创建 int LESS = -1;
// param 1: public static final
// param 2: 字段名称
// param 3: 字段类型
// param 4: 泛型
// param 5: 字段的值
// 由于这里没有注释,我们立即调用返回FieldVisitor的visitEnd方法,没有调用visitAnnotation或visitAttribute方法。
classWriter.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL, "LESS", "I", null, new Integer(-1)).visitEnd();
classWriter.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL, "EQUAL", "I", null, new Integer(0)).visitEnd();
classWriter.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL, "GREATER", "I", null, new Integer(1)).visitEnd();
classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "compareTo", "(Ljava/lang/Onbject;)I", null, null).visitEnd();
classWriter.visitEnd();
byte[] data = classWriter.toByteArray();
try {
FileOutputStream fos = new FileOutputStream(new File("Comparable.class"));
fos.write(data);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 使用创建好的class文件
Class clazz = new MyClassLoader().defineClass("com.asm.createclass.Comparable", data);
try {
Field field = clazz.getField("LESS");
Integer o = (Integer) field.get(null);
System.out.println(o.intValue()); // 输出-1
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
static class MyClassLoader extends ClassLoader {
public Class defineClass(String name, byte[] bytes) {
return defineClass(name, bytes, 0, bytes.length);
}
}
}
运行代码之后会创建一个 【Comparable.class】 文件。你可以使用IntellJ来查看,发现和我们预期的效果一致。