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來檢視,發現和我們預期的效果一緻。