凡是帶const的表示將什么數(shù)據(jù)壓操作數(shù)棧;如:
iconst_2 將int型數(shù)據(jù)2壓入到操作數(shù)棧;
aconst_null 將null值壓入棧;
bipush和sipush 表示將單字節(jié)或者短整形的常量值壓入操作數(shù)棧;
帶ldc的表示將什么類型數(shù)據(jù)從常量池中壓入到操作數(shù)棧;如:
ldc_w 將int或者flat或者string類型的數(shù)據(jù)壓入到操作數(shù)棧;
ldc2_w 將long或者double類型的數(shù)據(jù)壓入到操作數(shù)棧;
凡是帶load的指令表示將某類型的局部變量數(shù)據(jù)壓入到操作數(shù)棧的棧頂;如:
iload 表示將int類型的局部變量壓入到操作數(shù)棧的棧頂;
aload 以a開頭的表示將引用類型的局部變量壓入到操作數(shù)棧的棧頂;
iload_1 將局部變量數(shù)組里面下標(biāo)為1的int類型的數(shù)據(jù)壓入到操作數(shù)棧;
iaload 將int型數(shù)組的指定索引的值壓入到操作數(shù)棧;
凡是帶有store指令的表示將操作數(shù)棧頂?shù)哪愁愋偷闹荡嫒胫付ǖ木植孔兞恐?;如?istore 表示將棧頂int類型的數(shù)據(jù)存入到指定的局部變量中;
istore_3 表示將棧int類型的數(shù)據(jù)存入到局部變量數(shù)組的下標(biāo)為3的元素中;
pop 將棧頂數(shù)據(jù)彈出;pop2將棧頂?shù)囊粋€long或者double數(shù)據(jù)從棧頂彈出來;
dup 復(fù)制棧頂?shù)臄?shù)據(jù)并將復(fù)制的值也壓入到棧頂;
dup2 復(fù)制棧頂一個long或者是double的數(shù)據(jù)并將復(fù)制的值也壓入到棧頂;
swap 將棧最頂端的兩個值互換;
iadd 將棧頂兩個int型的數(shù)據(jù)相加然后將結(jié)果再次的壓入到棧頂;
isub 將棧頂兩個int型的數(shù)據(jù)相減然后將結(jié)果再次的壓入到棧頂;
imul 將棧頂兩個int型的數(shù)據(jù)相乘然后將結(jié)果再次的壓入到棧頂;
idiv 將棧頂兩個int型的數(shù)據(jù)相除然后將結(jié)果再次的壓入到棧頂;
irem 將棧頂兩個int型的數(shù)據(jù)取模運算然后將結(jié)果再次的壓入到棧頂;
ineg 將棧頂?shù)膇nt數(shù)據(jù)取負將結(jié)果壓入到棧頂;
iinc 將指定的int變量增加指定值(i++,i--,i+=2);
i2l 將棧頂int類型數(shù)據(jù)強制轉(zhuǎn)換成long型將結(jié)果壓入到棧頂;
lcmp 將棧頂兩long型數(shù)據(jù)的大小進行比較,并將結(jié)果(1,0,-1)壓入棧頂;
以if開頭的指令都是跳轉(zhuǎn)指令;
tableswitch、lookupswitch 表示用switch條件跳轉(zhuǎn);
ireturn 從當(dāng)前方法返回int型數(shù)據(jù);
getstatic 獲取指定類的靜態(tài)域,將將結(jié)果壓入到棧頂;
putstatic 為指定的類的靜態(tài)域賦值;
getfield 獲取指定類的實例變量,將結(jié)果壓入到棧頂;
putfield 為指定類的實例變量賦值;
invokevirtual 調(diào)用實例方法;
invokespacial 調(diào)用超類構(gòu)造方法,實例初始化方法,私有方法;
invokestatic 調(diào)用靜態(tài)方法;
invokeinterface 調(diào)用接口方法;
new 創(chuàng)建一個對象,并將其引用壓入到棧頂;
newarray 創(chuàng)建一個原始類型的數(shù)組,并將其引用壓入到棧頂;
arraylength 獲得一個數(shù)組的長度,將將結(jié)果壓入到棧頂;
athrow 將棧頂?shù)漠惓伋觯?checkcast 檢驗類型轉(zhuǎn)換,轉(zhuǎn)換未通過,將拋出ClassCastException.
instanceof 檢驗對象是否是指定的類的實例,如果是將1壓入棧頂,否則將0壓入棧頂
monitorenter 獲得對象的鎖,用于同步方法或同步塊
monitorexit 釋放對象的鎖,用于同步方法或同步塊
ifnull 為null時跳轉(zhuǎn)
ifnonnull 不為null時跳轉(zhuǎn)
字節(jié)碼指令如何工作?
所有字節(jié)碼指令都在Java虛擬機規(guī)范的第6章中指定。Is ASM thread safe?
The Type and ClassReader classes are thread safe, i.e. several threads can use a single Type object or a single ClassReader object concurrently without problems. The ClassWriter and MethodWriter classes are not thread safe, i.e. a single class cannot be generated by several concurrent threads (but, of course, several threads can generate distinct classes concurrently, if each thread uses its own ClassWriter instance). In order to generate a single class by using several concurrent threads, one should use ClassVisitor and MethodVisitor instances that delegate to normal ClassWriter and MethodWriter instances, and whose methods are all synchronized.
More generally, ClassVisitor and MethodVisitor implementations, such as ClassWriter, do not have to be thread safe. However, non thread safe visitors can be made thread safe just by using a synchronizing class adapter in front of them.
Type和ClassReader類是線程安全的,即多個線程可以同時使用單個Type對象或單個ClassReader對象而不會出現(xiàn)問題。ClassWriter和MethodWriter類不是 線程安全的,即幾個并發(fā)線程不能生成單個類(但是,當(dāng)然,如果每個線程使用自己的ClassWriter實例,則多個線程可以并發(fā)生成不同的類)。為了通過使用多個并發(fā)線程生成單個類,應(yīng)該使用委托給普通ClassWriter和MethodWriter實例的ClassVisitor和MethodVisitor實例,并且它們的方法都是同步的。
更一般地說,ClassVisitor和MethodVisitor實現(xiàn)(如ClassWriter)不必是線程安全的。但是,只要在它們前面使用同步類適配器,就可以使非線程安全訪問者成為線程安全的。-
ASM 提供了兩種編程模型
- Core API,提供了基于事件形式的編程模型。該模型不需要一次性將整個類的結(jié)構(gòu)讀取到內(nèi)存中,因此這種方式更快,需要更少的內(nèi)存。但這種編程方式難度較大。
- Tree API,提供了基于樹形的編程模型。該模型需要一次性將一個類的完整結(jié)構(gòu)全部讀取到內(nèi)存當(dāng)中,所以這種方法需要更多的內(nèi)存。這種編程方式較簡單。
- Core API 中操縱字節(jié)碼的功能基于 ClassVisitor 接口。這個接口中的每個方法對應(yīng)了 class 文件中的每一項。Class 文件中的簡單項的訪問使用一個單獨的方法,方法參數(shù)描述了這個項的內(nèi)容。而那些具有任意長度和復(fù)雜度的項,使用另外一類方法,這類方法會返回一個輔助的 Visitor 接口,通過這些輔助接口的對象來完成具體內(nèi)容的訪問。例如 visitField 方法和 visitMethod 方法,分別返回 FieldVisitor 和 MethodVisitor 接口的對象。
- ASM 提供了三個基于 ClassVisitor 接口的類來實現(xiàn) class 文件的生成和轉(zhuǎn)換:
- ClassReader:ClassReader 解析一個類的 class 字節(jié)碼,該類的 accept 方法接受一個 ClassVisitor 的對象,在 accept 方法中,會按上文描述的順序逐個調(diào)用 ClassVisitor 對象的方法。它可以被看做事件的生產(chǎn)者。
- ClassAdapter:ClassAdapter 是 ClassVisitor 的實現(xiàn)類。它的構(gòu)造方法中需要一個 ClassVisitor 對象,并保存為字段 protected ClassVisitor cv。在它的實現(xiàn)中,每個方法都是原封不動的直接調(diào)用 cv 的對應(yīng)方法,并傳遞同樣的參數(shù)??梢酝ㄟ^繼承 ClassAdapter 并修改其中的部分方法達到過濾的作用。它可以看做是事件的過濾器。
- ClassWriter:ClassWriter 也是 ClassVisitor 的實現(xiàn)類。ClassWriter 可以用來以二進制的方式創(chuàng)建一個類的字節(jié)碼。對于 ClassWriter 的每個方法的調(diào)用會創(chuàng)建類的相應(yīng)部分。例如:調(diào)用 visit 方法就是創(chuàng)建一個類的聲明部分,每調(diào)用一次 visitMethod 方法就會在這個類中創(chuàng)建一個新的方法。在調(diào)用 visitEnd 方法后即表明該類的創(chuàng)建已經(jīng)完成。它最終生成一個字節(jié)數(shù)組,這個字節(jié)數(shù)組中包含了一個類的 class 文件的完整字節(jié)碼內(nèi)容 ??梢酝ㄟ^ toByteArray 方法獲取生成的字節(jié)數(shù)組。ClassWriter 可以看做事件的消費者。
Asm簡單生成class示例
package com.coding.asm.test;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @Description: 通過ASM生成類的字節(jié)碼
*/
public class GeneratorClass {
public static void main(String[] args) throws IOException {
//① ClassReader:該類用來解析編譯過的class字節(jié)碼文件。
//② ClassWriter:該類用來重新構(gòu)建編譯后的類,比如說修改類名、屬性以及方法,甚至可以生成新的類的字節(jié)碼文件。
//③ ClassAdapter:該類也實現(xiàn)了ClassVisitor接口,它將對它的方法調(diào)用委托給另一個ClassVisitor對象。
//生成一個類只需要ClassWriter組件即可
ClassWriter cw = new ClassWriter(0);
//通過visit方法確定類的頭部信息
//一個編譯后的java類不包含package和import段,因此在class文件中所有的類型都使用的是全路徑。
//public final void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
// version:類版本
// access:類的訪問標(biāo)識
// name:類名稱
// signature:類簽名,如果類不是通用類,并且不擴展或?qū)崿F(xiàn)泛型類或接口,則可能為null。
// superName:超類名稱,如果是接口或超類為Object則可能為null
// interfaces:類實現(xiàn)的接口名稱列表
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT + Opcodes.ACC_INTERFACE,
"com/coding/asm/test/GenInterface", null, "java/lang/Object",
new String[]{"java/lang/Iterable"});
// 定義類的屬性
// public final FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
// access:字段訪問標(biāo)識
// name:字段名稱
// desc:字段描述
// signature:字段簽名,若字段類型不是泛型則可以為null
// value:字段初始值
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();
// 定義類的方法
// public final MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
// access:方法訪問標(biāo)識
// name:方法名稱
// desc:方法描述
// signature:方法簽名,若方法參數(shù)、返回類型和異常沒有使用泛型則可能為null
// exceptions:方法的異常名,可能為null
cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "compareTo",
"(Ljava/lang/Object;)I", null, null).visitEnd();
//使cw類已經(jīng)完成
cw.visitEnd();
//將cw轉(zhuǎn)換成字節(jié)數(shù)組寫到文件里面去
byte[] data = cw.toByteArray();
File file = new File("/Users/micocube/Documents/Utils4j/src/main/java/com/coding/asm/test/GenInterface.class");
FileOutputStream fos = new FileOutputStream(file);
fos.write(data);
fos.close();
}
}
- 生成的GenInterface.class文件反編譯后:
package com.coding.asm.test;
public interface GenInterface extends Iterable {
int LESS = -1;
int EQUAL = 0;
int GREATER = 1;
int compareTo(Object var1);
}
- 對類信息,字段信息,方法信息進行封裝(一直寫類的全限定名有點累):
package com.coding.asm.generator;
import org.objectweb.asm.Opcodes;
public class Header {
//public final void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
// version:類版本
// access:類的訪問標(biāo)識
// name:類名稱
// signature:類簽名,如果類不是通用類,并且不擴展或?qū)崿F(xiàn)泛型類或接口,則可能為null。
// superName:超類名稱,如果是接口或超類為Object則可能為null
// interfaces:類實現(xiàn)的接口名稱列表
private int version;
private int accessModifier = Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL;
private String className;
private String plasticity;
private String superClass;
private String[] interfaces;
public Header(int version, int accessModifier, String className, String plasticity, Class superClass, String[] interfaces) {
this.version = version;
this.accessModifier = accessModifier;
this.className = className;
this.plasticity = plasticity;
this.superClass = superClass.getName();
this.interfaces = interfaces;
}
public Header(int version, int accessModifier, String className, String plasticity, String superClass, String[] interfaces) {
this.version = version;
this.accessModifier = accessModifier;
this.className = className;
this.plasticity = plasticity;
this.superClass = superClass;
this.interfaces = interfaces;
}
public Header(int version, int accessModifier, String className, String plasticity, String[] interfaces) {
this.version = version;
this.accessModifier = accessModifier;
this.className = className;
this.plasticity = plasticity;
this.interfaces = interfaces;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public int getAccessModifier() {
return accessModifier;
}
public void setAccessModifier(int accessModifier) {
this.accessModifier = accessModifier;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getPlasticity() {
return plasticity;
}
public void setPlasticity(String plasticity) {
this.plasticity = plasticity;
}
public String getSuperClass() {
return superClass;
}
public void setSuperClass(String superClass) {
this.superClass = superClass;
}
public String[] getInterfaces() {
return interfaces;
}
public void setInterfaces(String[] interfaces) {
this.interfaces = interfaces;
}
}
package com.coding.asm.generator;
import org.objectweb.asm.Type;
public class Field {
// public final FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
// access:字段訪問標(biāo)識
// name:字段名稱
// desc:字段描述
// signature:字段簽名,若字段類型不是泛型則可以為null
// value:字段初始值
private int accessModifier;
private String fieldName;
private String fieldType;
private String plasticity;
private Object initValue;
public Field(int accessModifier, String fieldName, TypeDescriptor fieldType, String plasticity, Object initValue) {
this.accessModifier = accessModifier;
this.fieldName = fieldName;
this.fieldType = fieldType.getType();
this.plasticity = plasticity;
this.initValue = initValue;
}
public Field(int accessModifier, String fieldName, TypeDescriptor fieldType, String plasticity) {
this.accessModifier = accessModifier;
this.fieldName = fieldName;
this.fieldType = fieldType.getType();
this.plasticity = plasticity;
}
public Field(int accessModifier, String fieldName, Class fieldType, String plasticity, Object initValue) {
this.accessModifier = accessModifier;
this.fieldName = fieldName;
this.fieldType = SignUtils.class2SignStr(fieldType) + SignUtils.SEMICOLON;
this.plasticity = plasticity;
this.initValue = initValue;
}
public Field(int accessModifier, String fieldName, ClassType fieldType, String plasticity, Object initValue) {
this.accessModifier = accessModifier;
this.fieldName = fieldName;
//只有主類型 或者混合類型
if (fieldType.isFix() || fieldType.isOnlyPrimary()) {
this.fieldType = fieldType.getPrimaryType();
} else {
this.fieldType = Type.getType(Object.class).getDescriptor();
}
this.plasticity = plasticity;
this.initValue = initValue;
}
public Field(int accessModifier, String fieldName, String fieldType, String plasticity, Object initValue) {
this.accessModifier = accessModifier;
this.fieldName = fieldName;
this.fieldType = fieldType;
this.plasticity = plasticity;
this.initValue = initValue;
}
public int getAccessModifier() {
return accessModifier;
}
public void setAccessModifier(int accessModifier) {
this.accessModifier = accessModifier;
}
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public String getFieldType() {
return fieldType;
}
public void setFieldType(String fieldType) {
this.fieldType = fieldType;
}
public String getPlasticity() {
return plasticity;
}
public void setPlasticity(String plasticity) {
this.plasticity = plasticity;
}
public Object getInitValue() {
return initValue;
}
public void setInitValue(Object initValue) {
this.initValue = initValue;
}
}
public class Method {
// public final MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
// access:方法訪問標(biāo)識
// name:方法名稱
// desc:方法描述
// signature:方法簽名,若方法參數(shù)、返回類型和異常沒有使用泛型則可能為null
// exceptions:方法的異常名,可能為null
private int accessModifier = Opcodes.ACC_PUBLIC;
private String methodName;
private String argsDesc;
private String plasticity;
private String[] exceptions;
private TypeDesc typeDesc;
public Method(int accessModifier, String methodName, String argsDesc, String plasticity, String[] exceptions) {
this.accessModifier = accessModifier;
this.methodName = methodName;
this.argsDesc = argsDesc;
this.plasticity = plasticity;
this.exceptions = exceptions;
}
public Method(int accessModifier, String methodName, TypeDesc typeDesc, String[] exceptions) {
this.accessModifier = accessModifier;
this.methodName = methodName;
this.argsDesc = typeDesc.getDesc().toString();
this.plasticity = typeDesc.getSign().toString();
this.exceptions = exceptions;
}
public Method(int accessModifier, String methodName, String[] exceptions) {
this.accessModifier = accessModifier;
this.methodName = methodName;
this.argsDesc = argsDesc;
this.plasticity = plasticity;
this.exceptions = exceptions;
}
public int getAccessModifier() {
return accessModifier;
}
public void setAccessModifier(int accessModifier) {
this.accessModifier = accessModifier;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public String getArgsDesc() {
return argsDesc;
}
public void setArgsDesc(String argsDesc) {
this.argsDesc = argsDesc;
}
public String getPlasticity() {
return plasticity;
}
public void setPlasticity(String plasticity) {
this.plasticity = plasticity;
}
public String[] getExceptions() {
return exceptions;
}
public void setExceptions(String[] exceptions) {
this.exceptions = exceptions;
}
public TypeDesc getTypeDesc() {
return typeDesc;
}
public Method setTypeDesc(TypeDesc typeDesc) {
this.typeDesc = typeDesc;
return this;
}
}
- 類型描述符
package com.coding.asm.generator;
import java.util.Arrays;
public enum TypeDescriptor {
BOOL("Z"),
CHAR("C"),
BYTE("B"),
INT("I"),
FLOAT("F"),
LONG("J"),
SHORT("S"),
DOUBLE("D"),
VOID("V");
private String type;
private TypeDescriptor(String desc) {
this.type = desc;
}
public static TypeDescriptor toEnum(String type) {
TypeDescriptor[] value = new TypeDescriptor[]{null};
TypeDescriptor[] values = TypeDescriptor.values();
Arrays.stream(values).forEach(t -> {
if (t.getType().equals(type)) {
value[0] = t;
}
});
return value[0];
}
// Java type Type descriptor
// boolean Z
// char C
// byte B
// short S
// int I
// float F
// long J
// double D
// Object Ljava/lang/Object;
// int[] [I
// Object[][] [[Ljava/lang/Object;
public String getType() {
return this.type;
}
}
- 方法描述對象
package com.coding.asm.generator;
public class MethodDesc {
//方法的描述符
private StringBuilder desc = new StringBuilder();
//方法簽名
private StringBuilder sign = new StringBuilder();
public StringBuilder getDesc() {
return desc;
}
public MethodDesc setDesc(StringBuilder desc) {
this.desc = desc;
return this;
}
public StringBuilder getSign() {
return sign;
}
public MethodDesc setSign(StringBuilder sign) {
this.sign = sign;
return this;
}
}
- 類型對象[解決類的全限定名]
package com.coding.asm.generator;
import org.objectweb.asm.Type;
/**
* Created by micocube
* ProjectName: coding
* PackageName: com.mico.test.asm
* User: micocube
* Email: ldscube@gmail.com
* CreateTime: 2018/12/27下午2:15
* ModifyTime: 2018/12/27下午2:15
* Version: 0.1
* Description:
**/
public class ClassType {
// 主類型的原始class
private Class primaryOriginalClass;
// 主類型
private String primaryType;
// 范型
private String[] plasticity;
// 只有范型
private Boolean onlyPlasticity = false;
// 只有主類型
private Boolean onlyPrimary = false;
// 混合類型
private Boolean fix = false;
// 范型是具體類型
private Boolean plasticityTypeIsParticular = false;
// 是否是數(shù)組
private Boolean isArray = false;
// 是否是原始類型
private Boolean isPrimitive = false;
/**
* 只有主類型,沒有范型 eg:java.util.Map
*
* @param primaryType
*/
public ClassType(Class primaryType) {
this.primaryOriginalClass = primaryType;
this.onlyPrimary = true;
String descriptor = getDescriptor(primaryType);
if (primaryType.isPrimitive()) {
this.isPrimitive = true;
this.primaryType = descriptor;
} else if (primaryType.isArray()) {
this.isArray = true;
}
descriptor = descriptor.endsWith(SignUtils.SEMICOLON) ? descriptor.substring(0, descriptor.length() - 2) : descriptor;
this.primaryType = descriptor;
}
/**
* 原始類型
*
* @param primaryType
*/
public ClassType(TypeDescriptor primaryType) {
this.primaryType = primaryType.getType();
this.onlyPrimary = true;
this.isPrimitive = true;
}
/**
* 純范型 比如 T
*
* @param plasticity
*/
public ClassType(String... plasticity) {
this.plasticity = plasticity;
this.onlyPlasticity = true;
}
/**
* 混合類型,帶范型 eg:java.util.Map<K,V>
*
* @param primaryType
* @param plasticity
*/
public ClassType(Class primaryType, String... plasticity) {
this.primaryOriginalClass = primaryType;
this.plasticity = plasticity;
this.primaryType = getDescriptor(primaryType);
this.fix = true;
}
/**
* 混合類型,帶具體類型 eg: java.util.Map<String,Object>
*
* @param primaryType
* @param plasticity
*/
public ClassType(Class primaryType, Class... plasticity) {
this.primaryOriginalClass = primaryType;
String[] ps = new String[plasticity.length];
for (int i = 0; i < plasticity.length; i++) {
ps[i] = getDescriptor(plasticity[i]);
}
this.plasticity = ps;
this.primaryType = getDescriptor(primaryType);
this.fix = true;
this.plasticityTypeIsParticular = true;
}
public static ClassType get(Class type) {
return new ClassType(type);
}
public static ClassType get(TypeDescriptor type) {
return new ClassType(type);
}
public static ClassType get(String... plasticity) {
return new ClassType(plasticity);
}
public static ClassType get(Class primaryType, String... plasticity) {
return new ClassType(primaryType, plasticity);
}
public static ClassType get(Class primaryType, Class... plasticity) {
return new ClassType(primaryType, plasticity);
}
private String getDescriptor(Class primaryType) {
String descriptor = Type.getType(primaryType).getDescriptor();
descriptor = descriptor.endsWith(SignUtils.SEMICOLON) ? descriptor.substring(0, descriptor.length() - 1) : descriptor;
return descriptor;
}
public Class getPrimaryOriginalClass() {
return primaryOriginalClass;
}
public String getPrimaryType() {
return primaryType;
}
public String[] getPlasticity() {
return plasticity;
}
public Boolean isOnlyPlasticity() {
return onlyPlasticity;
}
public Boolean isOnlyPrimary() {
return onlyPrimary;
}
public Boolean isFix() {
return fix;
}
public Boolean plasticityTypeIsParticular() {
return plasticityTypeIsParticular;
}
public Boolean isArray() {
return isArray;
}
public Boolean isPrimitive() {
return isPrimitive;
}
}
- 簽名生成工具類
package com.coding.asm.generator;
import org.objectweb.asm.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* Created by micocube
* ProjectName: coding
* PackageName: com.mico.test.asm
* User: micocube
* Email: ldscube@gmail.com
* CreateTime: 2018/12/27下午4:18
* ModifyTime: 2018/12/27下午4:18
* Version: 0.1
* Description:
**/
public class SignUtils {
public static final String CLASS_START = "L";
public static final String SEMICOLON = ";";
public static final String COLON = ":";
public static final String ANGLE_BRACKET_LEFT = "<";
public static final String ANGLE_BRACKET_RIGHT = ">";
public static final String DIAGONAL = "/";
public static final String DOT = ".";
public static final String PLASTICITY_TYPE = "T";
public static final String BRACKET_LEFT = "(";
public static final String BRACKET_RIGHT = ")";
/**
* 生成簡單的類簽名
* eg: Abc<T, U> extends LinkedHashMap<T, U> implements Iterable<T, U>
* 簽名: <T:Ljava/lang/Object;U:Ljava/lang/Object;>Ljava/util/LinkedHashMap<TT;TU;>;Ljava/lang/Iterable<TT>;
* 使用方法:
* String s = utils.genClassSimpleSign(new String[]{"T", "U"},
* new LinkedHashMap<Class, String[]>() {{
* put(LinkedHashMap.class, new String[]{"T","U"});
* }},
* new LinkedHashMap<Class, String[]>() {{
* put(Iterable.class, new String[]{"T"});
* }}
* );
*
* @param classPlasticity
* @param superClassPlasticity
* @param interface_plasticity
* @return
*/
public static String genClassSimpleSign(
List<String> classPlasticity,
ClassType superClassPlasticity,
List<ClassType> interface_plasticity
) {
StringBuilder sign = new StringBuilder();
//類范性
classPlasticity(sign, classPlasticity);
//超類簽名
superClassPlasticity(sign, superClassPlasticity, classPlasticity);
//接口簽名
interfacePlasticity(sign, interface_plasticity, classPlasticity);
return sign.toString();
}
//Iterable.class T,U
private static void interfacePlasticity(StringBuilder sign, List<ClassType> interface_plasticity, List<String> classPlasticity) {
interfaceSuperClassPlasticity(sign, interface_plasticity);
}
// 超類范型簽名
private static void superClassPlasticity(StringBuilder sign, ClassType superClassPlasticity, List<String> classPlasticity) {
if (null == superClassPlasticity) {
sign.append(class2SignStr(Object.class)).append(SEMICOLON);
return;
}
interfaceSuperClassPlasticity(sign, Arrays.asList(superClassPlasticity));
}
// 接口范型簽名
private static void interfaceSuperClassPlasticity(StringBuilder sign, List<ClassType> classPlasticity) {
classPlasticity.forEach((classType) -> {
String primaryType = classType.getPrimaryType();
String[] plasticity = classType.getPlasticity();
if (null == plasticity || plasticity.length == 0) {
sign.append(primaryType);
} else {
sign.append(primaryType).append(ANGLE_BRACKET_LEFT);
Arrays.stream(plasticity).forEach(ps -> {
sign.append(PLASTICITY_TYPE).append(ps).append(SEMICOLON);
});
sign.append(ANGLE_BRACKET_RIGHT);
}
sign.append(SEMICOLON);
});
}
/**
* 類范型
*
* @param sign
* @param plasticity
*/
private static void classPlasticity(StringBuilder sign, List<String> plasticity) {
if (Objects.nonNull(plasticity) && plasticity.size() != 0) {
sign.append(ANGLE_BRACKET_LEFT);
plasticity.stream().forEach(p -> {
sign.append(p)
.append(COLON)
.append(class2SignStr(Object.class))
.append(SEMICOLON);
});
sign.append(ANGLE_BRACKET_RIGHT);
}
}
/**
* class 轉(zhuǎn)成 類簽名
*
* @param clazz
* @return
*/
public static String class2SignStr(Class<?> clazz) {
return CLASS_START + class2TypeStr(clazz);
}
/**
* class 轉(zhuǎn)成用/分割的類全路徑
*
* @param clazz
* @return
*/
public static String class2TypeStr(Class<?> clazz) {
return clazz.getName().replace(DOT, DIAGONAL);
}
/**
* 生成屬性簽名
*
* @param classType
* @param classPlasticity
* @return
*/
public static String genFieldSimpleSign(ClassType classType, List<String> classPlasticity) {
StringBuilder stringBuilder = new StringBuilder();
interfacePlasticity(stringBuilder, Arrays.asList(classType), classPlasticity);
return stringBuilder.toString();
}
/**
* 生成方法簽名
*
* @param returnType
* @param argsTypes
* @param classPlasticity
* @return
*/
public static MethodDesc genMethodSign(ClassType returnType, List<ClassType> argsTypes, List<String> classPlasticity) {
MethodDesc typeDesc = new MethodDesc();
genMethodArgsTypeSimpleSign(typeDesc, argsTypes, classPlasticity);
genMethodReturnTypeSimpleSign(typeDesc, returnType, classPlasticity);
return typeDesc;
}
/**
* 生成返回類型簽名
*
* @param returnType 返回類型,返回類型范性
* @return
*/
private static MethodDesc genMethodReturnTypeSimpleSign(MethodDesc typeDesc, ClassType returnType, List<String> classPlasticity) {
StringBuilder sign = typeDesc.getSign();
StringBuilder desc = typeDesc.getDesc();
String[] plasticity = returnType.getPlasticity();
String primaryType = returnType.getPrimaryType();
if (returnType.isOnlyPrimary()) {
if (null != TypeDescriptor.toEnum(primaryType)) {
sign
.append(primaryType);
desc
.append(primaryType);
} else {
sign
.append(primaryType)
.append(SEMICOLON)
;
desc
.append(primaryType)
.append(SEMICOLON)
;
}
} else if (returnType.isOnlyPlasticity()) {
if (plasticity.length != 1) {
throw new IllegalArgumentException("只允許一個返回類型!");
}
sign.append(PLASTICITY_TYPE)
.append(plasticity[0]);
desc
.append(class2SignStr(Object.class));
desc.append(SEMICOLON);
sign.append(SEMICOLON);
} else if (returnType.isFix()) {
sign.append(primaryType)
.append(ANGLE_BRACKET_LEFT);
desc.append(primaryType);
genFixTypeSign(sign, desc, returnType, plasticity);
sign.append(ANGLE_BRACKET_RIGHT);
desc.append(SEMICOLON);
sign.append(SEMICOLON);
}
return typeDesc;
}
/**
* 生成參數(shù)簽名
* (TT;TU;)
* <p>
* (ILjava/lang/String;[[Lcom/sosnoski/generics/FileInfo;)V
* void mmm(int x, String y, FileInfo[][] z)
*
* @param types 參數(shù)類型,參數(shù)類型范型
* @param classPlasticity
* @return
*/
private static MethodDesc genMethodArgsTypeSimpleSign(MethodDesc typeDesc, List<ClassType> types, List<String> classPlasticity) {
StringBuilder sign = typeDesc.getSign();
sign.append(BRACKET_LEFT);
StringBuilder desc = typeDesc.getDesc();
desc.append(BRACKET_LEFT);
types.forEach(classType -> {
String[] plasticity = classType.getPlasticity();
String primaryType = classType.getPrimaryType();
if (classType.isOnlyPrimary()) {
sign
.append(primaryType);
desc
.append(primaryType);
if (!classType.isPrimitive()) {
sign.append(SEMICOLON);
desc.append(SEMICOLON);
}
} else if (classType.isOnlyPlasticity()) {
Arrays.stream(plasticity).forEach(p -> {
sign
.append(PLASTICITY_TYPE)
.append(p)
.append(SEMICOLON);
desc.append(Type.getType(Object.class));
});
} else if (classType.isFix()) {
sign.append(primaryType);
sign.append(ANGLE_BRACKET_LEFT);
desc.append(primaryType);
genFixTypeSign(sign, desc, classType, plasticity);
sign.append(ANGLE_BRACKET_RIGHT);
}
});
sign.append(BRACKET_RIGHT);
desc.append(BRACKET_RIGHT);
return typeDesc;
}
private static void genFixTypeSign(StringBuilder sign, StringBuilder desc, ClassType classType, String[] plasticity) {
//具體的范型
if (classType.plasticityTypeIsParticular()) {
Arrays.stream(plasticity).forEach(p -> {
sign
.append(p)
.append(SEMICOLON);
});
} else {
// T 類型的范型
Arrays.stream(plasticity).forEach(p -> {
sign
.append(PLASTICITY_TYPE)
.append(p)
.append(SEMICOLON);
});
}
}
}
- ASM 字節(jié)碼生成工具類
package com.coding.asm.generator;
import org.apache.log4j.Logger;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
/**
* Created by micocube
* ProjectName: coding
* PackageName: com.mico.test.asm
* User: micocube
* Email: ldscube@gmail.com
* CreateTime: 2018/12/20下午4:20
* ModifyTime: 2018/12/20下午4:20
* Version: 0.1
* Description: ASM 工具類
* https://victorzhzh.iteye.com/category/140253
* https://blog.csdn.net/Mr__fang/article/details/54846502
* ASM requires a JDK 1.5 or above.
* mv = cw.visitMethod(ACC_PUBLIC, "getList","(Ljava/util/Map;)Ljava/util/List;","(Ljava/util/Map<Ljava/lang/String;Ljava/lang/Integer;>;)Ljava/util/List<Ljava/lang/String;>;",null);
**/
public class AsmUtils {
private Logger logger = Logger.getLogger(AsmUtils.class);
private ClassWriter cw;
public AsmUtils(ClassWriter cw) {
this.cw = cw;
}
public AsmUtils() {
this.cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
}
public ClassWriter getCw() {
return cw;
}
/**
* 寫Class 頭
*
* @param header
*/
public void writerHeader(Header header) {
cw.visit(
header.getVersion(),
header.getAccessModifier(),
header.getClassName(),
header.getPlasticity(),
header.getSuperClass(),
header.getInterfaces()
);
}
public void writeClassHeader(
// 字節(jié)碼版本
int version,
// 類權(quán)限修飾符
int accessModifier,
// 類名
String className,
// 超類
Class superClass,
// 接口列表
List<Class> interfacesClass,
// 類中所有的范型列表,eg:K,V
List<String> classPlasticity,
// 超類范型
ClassType superClassPlasticity,
// 接口范型
List<ClassType> interfacesClassPlasticity
) {
String[] interfaces = null;
if (null != interfacesClass && interfacesClass.size() != 0) {
interfaces = new String[interfacesClass.size()];
for (int i = 0; i < interfacesClass.size(); i++) {
Class c = interfacesClass.get(i);
interfaces[i] = SignUtils.class2TypeStr(c);//接口不加L前綴
}
}
String superStr = null;
if (null != superClass) {
superStr = SignUtils.class2TypeStr(superClass);//超類不加L前綴
}
String sign = SignUtils.genClassSimpleSign(classPlasticity, superClassPlasticity, interfacesClassPlasticity);
System.out.println("class sign:" + sign);
Header header = new Header(version,
accessModifier,
className,
sign,
superStr,
interfaces);
writerHeader(header);
}
/**
* 寫Field
*
* @param field
*/
public void writeField(Field field) {
cw.visitField(
field.getAccessModifier(),
field.getFieldName(),
field.getFieldType(),
field.getPlasticity(),
field.getInitValue()
).visitEnd();
}
/**
* 寫field
*
* @param accessModifier
* @param fieldName
* @param classType
* @param classPlasticity
* @param initValule
*/
public void writeField(int accessModifier, String fieldName, ClassType classType, List<String> classPlasticity, Object initValule) {
boolean primitiveOrArray = classType.isPrimitive() || classType.isArray() || classType.isOnlyPrimary();
String sign = primitiveOrArray ? null : SignUtils.genFieldSimpleSign(
classType,
classPlasticity);
String primaryType = classType.getPrimaryType();
//原始類型不加分號
if (!classType.isPrimitive()) {
primaryType = primaryType + SignUtils.SEMICOLON;
}
System.out.println("Field Name:" + fieldName + "###Desc:" + primaryType + "####Sign:" + sign);
// 非final 不要給初始值,沒用,即使是final 也要是原始類型,才能反編譯后顯示初始值
Field field = new Field(accessModifier, fieldName, primaryType, sign, initValule);
writeField(field);
}
/**
* 寫方法頭
*
* @param method
* @return
*/
public GeneratorAdapter writeMethodHeader(Method method) {
MethodVisitor methodVisitor = cw.visitMethod(
method.getAccessModifier(),
method.getMethodName(),
method.getArgsDesc(),
method.getPlasticity(),
method.getExceptions()
);
org.objectweb.asm.commons.Method asmMethod =
new org.objectweb.asm.commons.Method(method.getMethodName(),
method.getTypeDesc().getDesc().toString());
GeneratorAdapter adapter = new GeneratorAdapter(method.getAccessModifier(),
asmMethod, methodVisitor);
return adapter;
}
/**
* 寫方法,返回MethodVisitor
*
* @param method
* @return
*/
public MethodVisitor writeMethod(Method method) {
return cw.visitMethod(
method.getAccessModifier(),
method.getMethodName(),
method.getArgsDesc(),
method.getPlasticity(),
method.getExceptions()
);
}
public void close() {
cw.visitEnd();
}
public byte[] toByteArray() {
return cw.toByteArray();
}
public void writeClass(String path) throws Exception {
byte[] bytes = toByteArray();
writeClass(path, bytes);
}
public void writeClass(String path, byte[] bytes) throws Exception {
File file = new File(path);
FileOutputStream fos = new FileOutputStream(file);
fos.write(bytes);
fos.close();
}
public Method genMethod(int accessModifier, String methodName, ClassType returnType, List<ClassType> argsTypes, List<String> classPlasticity, String[] exceptions) {
MethodDesc typeDesc = SignUtils.genMethodSign(returnType, argsTypes, classPlasticity);
Method method = new Method(accessModifier,
methodName,
typeDesc.getDesc().toString(),
typeDesc.getSign().toString(),
exceptions);
method.setTypeDesc(typeDesc);
System.out.println("Method:" + methodName + "###,Method Sign:" + typeDesc.getSign() + "###,Method desc:" + typeDesc.getDesc());
return method;
}
/**
* 靜態(tài)變量入棧
*
* @param adapter
* @param classType
* @param fieldName
* @param fieldType
*/
public void allocateStaticField(GeneratorAdapter adapter, Class classType, String fieldName, Class fieldType) {
adapter.getStatic(Type.getType(classType), fieldName, Type.getType(fieldType));
}
/**
* 調(diào)用靜態(tài)方法
*
* @param adapter
* @param methodDesc 返回值 方法名 (參數(shù)列表) eg: Integer valueOf (int)
*/
public void allocateStaticMethod(GeneratorAdapter adapter, Class classType, String methodDesc) {
adapter.invokeStatic(Type.getType(classType), org.objectweb.asm.commons.Method.getMethod(methodDesc));
}
/**
* 調(diào)用對象方法
*
* @param adapter
* @param classType
* @param methodDesc
*/
public void allocateMethod(GeneratorAdapter adapter, Class classType, String methodDesc) {
adapter.invokeVirtual(Type.getType(classType), org.objectweb.asm.commons.Method.getMethod(methodDesc));
}
/**
* 調(diào)用System.out.println(String)
*
* @param adapter
* @param print
*/
public void allocatePrintln(GeneratorAdapter adapter, String print) {
allocateStaticField(adapter, System.class, "out", PrintStream.class);
adapter.push(print);
allocateMethod(adapter, PrintStream.class, "void println (String)");
}
/**
* 調(diào)用構(gòu)造方法
*
* @param adapter
*/
public void allocateConstructor(GeneratorAdapter adapter, Class classType) {
adapter.invokeConstructor(Type.getType(classType), org.objectweb.asm.commons.Method.getMethod("void <init> ()"));
}
/**
* 創(chuàng)建方法域內(nèi)的局部變量
*
* @param adapter
* @param classType
*/
public void allocateNewObject(GeneratorAdapter adapter, Class classType) {
adapter.newInstance(Type.getType(classType));
adapter.dup();
allocateConstructor(adapter, classType);
adapter.visitVarInsn(Opcodes.ASTORE, 1);
adapter.visitVarInsn(Opcodes.ALOAD, 1);
}
/**
* 方法返回null
*
* @param adapter
*/
public void allocateReturnNull(GeneratorAdapter adapter) {
adapter.visitInsn(Opcodes.ACONST_NULL);
adapter.visitMaxs(0, 0);
returnAndEndMethod(adapter);
}
/**
* 生成默認無參的構(gòu)造方法,調(diào)用超類的構(gòu)造方法
*
* @param adapter
* @param superClass 超類
*/
public void genDefaultConstructor(GeneratorAdapter adapter, Class superClass) {
adapter.loadThis();
adapter.invokeConstructor(Type.getType(superClass), org.objectweb.asm.commons.Method.getMethod("void <init> ()"));
}
/**
* 生成默認無參的構(gòu)造方法,調(diào)用超類的構(gòu)造方法
*
* @param adapter
* @param superClass 超類
*/
public void genDefaultConstructor(GeneratorAdapter adapter, String superClass) {
adapter.loadThis();
Type type = Type.getType(superClass);
logger.debug("<init>: super class:" + type.getDescriptor());
adapter.invokeConstructor(type, org.objectweb.asm.commons.Method.getMethod("void <init> ()"));
}
/**
* 結(jié)束方法
*
* @param adapter
*/
public void returnAndEndMethod(GeneratorAdapter adapter) {
// 缺少returnValue 將導(dǎo)致
// 錯誤: 無法初始化主類 Abc
//原因: java.lang.VerifyError: Control flow falls through code end
//Exception Details:
// Location:
// Abc.main([Ljava/lang/String;)V @8: <invalid>
// Reason:
// Error exists in the bytecode
// Bytecode:
// 0000000: b200 2212 24b6 002a
adapter.returnValue();
//如何讓ASM為我計算visitMaxs?
//調(diào)用ClassWriter的構(gòu)造函數(shù)時,請使用COMPUTE_MAXS標(biāo)志。
// 您還必須包含visitMaxs方法調(diào)用,但忽略您給出的值,因此visitMaxs(0,0)沒問題。
adapter.visitMaxs(0, 0);
//缺少這句將導(dǎo)致java.lang.VerifyError:
// (class: Abc, method: main signature: ([Ljava/lang/String;)V) Stack size too large
adapter.endMethod();
}
/**
* 創(chuàng)建Setter
*
* @param className
* @param fieldType
* @param fieldName
* @param classPlasticity
*/
public void createSetter(String className, ClassType fieldType, String fieldName, List<String> classPlasticity) {
String methodName = "set" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
// MethodVisitor mv =
// cw.visitMethod(Opcodes.ACC_PUBLIC, methodName, "(" + type + ")V", null, null);
// mv.visitVarInsn(Opcodes.ALOAD, 0);
// mv.visitVarInsn(Type.getType(c).getOpcode(Opcodes.ILOAD), 1);
// mv.visitFieldInsn(Opcodes.PUTFIELD, className, propertyName, type);
// mv.visitInsn(RETURN);
// mv.visitMaxs(0, 0);
Method init = genMethod(Opcodes.ACC_PUBLIC, methodName, new ClassType(TypeDescriptor.VOID),
new ArrayList() {{
add(fieldType);
}}, classPlasticity, null);
GeneratorAdapter setterAdapter = writeMethodHeader(init);
setterAdapter.visitVarInsn(Opcodes.ALOAD, 0);
setterAdapter.visitVarInsn(Type.getType(fieldType.getPrimaryOriginalClass()).getOpcode(Opcodes.ILOAD), 1);
setterAdapter.putField(Type.getType(className), fieldName, Type.getType(fieldType.getPrimaryOriginalClass()));
returnAndEndMethod(setterAdapter);
}
/**
* 創(chuàng)建Getter
*
* @param className
* @param fieldType
* @param fieldName
* @param classPlasticity
*/
public void createGetter(String className, ClassType fieldType, String fieldName, List<String> classPlasticity) {
String methodName = "get" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
// MethodVisitor mv =
// cw.visitMethod(Opcodes.ACC_PUBLIC, methodName, "()" + returnType, null, null);
// mv.visitVarInsn(Opcodes.ALOAD, 0);
// mv.visitFieldInsn(Opcodes.GETFIELD, internalClassName, propertyName, returnType);
// mv.visitInsn(Type.getType(c).getOpcode(Opcodes.IRETURN));
// mv.visitMaxs(0, 0);
Method init = genMethod(Opcodes.ACC_PUBLIC, methodName, fieldType,
new ArrayList() {{
}}, classPlasticity, null);
GeneratorAdapter getterAdapter = writeMethodHeader(init);
getterAdapter.visitVarInsn(Opcodes.ALOAD, 0);
getterAdapter.getField(Type.getType(className), fieldName, Type.getType(fieldType.getPrimaryOriginalClass()));
returnAndEndMethod(getterAdapter);
}
}
- 使用示例[1]:
package com.coding.asm.test;
import com.coding.asm.generator.*;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.GeneratorAdapter;
import java.io.File;
import java.util.*;
/**
* Created by micocube
* ProjectName: coding
* PackageName: com.mico.test.asm
* User: micocube
* Email: ldscube@gmail.com
* CreateTime: 2018/12/20下午4:42
* ModifyTime: 2018/12/20下午4:42
* Version: 0.1
* Description:
**/
public class Test {
public static void main(String[] args)throws Exception {
AsmUtils utils = new AsmUtils();
List<String> classPlasticity = Arrays.asList("T", "U");
String className = "Abc";
utils.writeClassHeader(
Opcodes.V1_8,
Opcodes.ACC_PUBLIC,
className,
LinkedHashMap.class,
Arrays.asList(Iterable.class),
Arrays.asList("K","V"),
new ClassType(LinkedHashMap.class,"K","V"),
Arrays.asList(new ClassType(Iterable.class,"K"))
);
utils.writeField(Opcodes.ACC_PRIVATE+Opcodes.ACC_STATIC,
"a",
ClassType.get(int.class),
classPlasticity,
Integer.valueOf(100)
);
utils.createGetter(className,ClassType.get(int.class),"a",classPlasticity);
utils.createSetter(className,ClassType.get(int.class),"a",classPlasticity);
// 非final 不要給初始值,沒用,即使是final 也要是原始類型,才能反編譯后顯示初始值
utils.writeField(Opcodes.ACC_PRIVATE+Opcodes.ACC_STATIC+Opcodes.ACC_FINAL,
"b",
ClassType.get(TypeDescriptor.DOUBLE),
classPlasticity,
Double.valueOf("1000.01")
);
utils.writeField(Opcodes.ACC_PRIVATE,
"c",
ClassType.get(Map.class,new String[]{"K", "V"}),
classPlasticity,
null
);
utils.createGetter(className,ClassType.get(Map.class),"c",classPlasticity);
utils.createSetter(className,ClassType.get(Map.class),"c",classPlasticity);
Method init = utils.genMethod(Opcodes.ACC_PUBLIC,"<init>",new ClassType(TypeDescriptor.VOID),
new ArrayList() {{}}, classPlasticity,null);
GeneratorAdapter initAdapter = utils.writeMethodHeader(init);
utils.genDefaultConstructor(initAdapter,LinkedHashMap.class);
utils.returnAndEndMethod(initAdapter);
// (TT;TU;)V
Method iterator2 = utils.genMethod(Opcodes.ACC_PUBLIC,"iterator2",new ClassType(Iterator.class),
new ArrayList() {{
add(new ClassType("K"));
add(new ClassType("V"));
}}, classPlasticity,null);
GeneratorAdapter generatorAdapter = utils.writeMethodHeader(iterator2);
utils.allocateReturnNull(generatorAdapter);
Method iterator = utils.genMethod(Opcodes.ACC_PUBLIC,"iterator",new ClassType(Iterator.class,"K"),
new ArrayList() {{}}, classPlasticity,null);
GeneratorAdapter iteratorAdapter = utils.writeMethodHeader(iterator);
utils.allocateReturnNull(iteratorAdapter);
Method compare = utils.genMethod(Opcodes.ACC_PUBLIC,"compareTo",new ClassType(Integer.class),
new ArrayList() {{
add(new ClassType(Integer.class));
}}, classPlasticity,null);
GeneratorAdapter adapter = utils.writeMethodHeader(compare);
adapter.loadArg(0);
utils.returnAndEndMethod(adapter);
Method getA = utils.genMethod(Opcodes.ACC_PUBLIC,"getA",new ClassType("K"),
new ArrayList() {{add(new ClassType("V"));}}, classPlasticity,null);
GeneratorAdapter getAdapter = utils.writeMethodHeader(getA);
utils.allocateReturnNull(getAdapter);
Method get = utils.genMethod(Opcodes.ACC_PUBLIC,"get",new ClassType(List.class,File.class),
new ArrayList() {{}}, classPlasticity,null);
GeneratorAdapter mg = utils.writeMethodHeader(get);
utils.allocateNewObject(mg,ArrayList.class);
utils.returnAndEndMethod(mg);
//
Method main = utils.genMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC,"main",new ClassType(TypeDescriptor.VOID),
new ArrayList() {{add(new ClassType(String[].class));}}, classPlasticity,null);
GeneratorAdapter mainAdapter = utils.writeMethodHeader(main);
utils.allocatePrintln(mainAdapter,"Hello Main!");
utils.returnAndEndMethod(mainAdapter);
Method print = utils.genMethod(Opcodes.ACC_PUBLIC ,
"print",new ClassType(TypeDescriptor.VOID),
new ArrayList() {{}}, classPlasticity,null);
GeneratorAdapter printAdapter = utils.writeMethodHeader(print);
utils.allocatePrintln(printAdapter,"Hello ASM!");
utils.returnAndEndMethod(printAdapter);
utils.close();
utils.writeClass("./target/classes/Abc.class");
}
}
- 生成的Abc.class 反編譯:
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class Abc<K, V> extends LinkedHashMap<K, V> implements Iterable<K> {
private static int a;
private static final double b = 1000.01D;
private Map<K, V> c;
public int getA() {
return this.a;
}
public void setA(int var1) {
this.a = var1;
}
public Map getC() {
return this.c;
}
public void setC(Map var1) {
this.c = var1;
}
public Abc() {
}
public Iterator iterator2(K var1, V var2) {
return null;
}
public Iterator<K> iterator() {
return null;
}
public Integer compareTo(Integer var1) {
return var1;
}
public K getA(V var1) {
return null;
}
public List<File> get() {
ArrayList var1 = new ArrayList();
return var1;
}
public static void main(String[] var0) {
System.out.println("Hello Main!");
}
public void print() {
System.out.println("Hello ASM!");
}
}
- 切換到Abc.class文件路徑,執(zhí)行
| => java Abc
# 說明生成成功而且字節(jié)碼沒問題
Hello Main!
- 使用示例[2]
package com.coding.asm.test;
import com.coding.asm.generator.*;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.GeneratorAdapter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by micocube
* ProjectName: coding
* PackageName: com.mico.test.asm
* User: micocube
* Email: ldscube@gmail.com
* CreateTime: 2018/12/20下午4:42
* ModifyTime: 2018/12/20下午4:42
* Version: 0.1
* Description:
**/
public class TestBcd {
public static void main(String[] args)throws Exception {
AsmUtils utils = new AsmUtils();
SignUtils signUtils = new SignUtils();
List<String> classPlasticity = null;
utils.writeClassHeader(
Opcodes.V1_7,
Opcodes.ACC_PUBLIC,
"Bcd",
SignUtils.class,
Arrays.asList(Comparable.class),
classPlasticity,
new ClassType(SignUtils.class),
Arrays.asList(new ClassType(Comparable.class))
);
utils.writeField(Opcodes.ACC_PRIVATE+Opcodes.ACC_STATIC+Opcodes.ACC_FINAL,
"a",
ClassType.get(int.class),
classPlasticity,
Integer.valueOf(100)
);
Method init = utils.genMethod(Opcodes.ACC_PUBLIC,"<init>",new ClassType(TypeDescriptor.VOID),
new ArrayList() {{}}, classPlasticity,null);
GeneratorAdapter initAdapter = utils.writeMethodHeader(init);
utils.genDefaultConstructor(initAdapter,SignUtils.class);
utils.returnAndEndMethod(initAdapter);
/**
*
public int compareTo(Object o) {
return 0;
}
*/
Method compareTo = utils.genMethod(Opcodes.ACC_PUBLIC,"compareTo",new ClassType(int.class),
new ArrayList() {{
add(new ClassType(Object.class));
}}, classPlasticity,null);
GeneratorAdapter compareToAdapter = utils.writeMethodHeader(compareTo);
compareToAdapter.push(0);
utils.returnAndEndMethod(compareToAdapter);
//
Method main = utils.genMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC,"main",new ClassType(TypeDescriptor.VOID),
new ArrayList() {{add(new ClassType(String[].class));}}, classPlasticity,null);
GeneratorAdapter mainAdapter = utils.writeMethodHeader(main);
utils.allocatePrintln(mainAdapter,"Hello Bcd!");
utils.returnAndEndMethod(mainAdapter);
Method print = utils.genMethod(Opcodes.ACC_PUBLIC ,
"print",new ClassType(TypeDescriptor.VOID),
new ArrayList() {{}}, classPlasticity,null);
GeneratorAdapter printAdapter = utils.writeMethodHeader(print);
utils.allocatePrintln(printAdapter,"Hello Print!");
utils.returnAndEndMethod(printAdapter);
utils.close();
utils.writeClass("./target/classes/Bcd.class");
}
}
- 反編譯Bcd.class
package com.coding.asm.test;
import com.coding.asm.generator.SignUtils;
public class Bcd extends SignUtils implements Comparable {
private static final int a = 100;
public Bcd() {
}
public int compareTo(Object var1) {
return 0;
}
public static void main(String[] var0) {
System.out.println("Hello BCD!");
}
public void print() {
System.out.println("Hello Print!");
}
}
- 切換到Bcd.class文件路徑,執(zhí)行
# 說明生成成功而且字節(jié)碼沒問題
| => java Bcd
Hello Bcd!