- Java javap命令(Version-java9)
- Java class 文件结构(Version-java8)
- 字节码指令介绍:
凡是带const的表示将什么数据压操作数栈;如:
iconst_2 将int型数据2压入到操作数栈;
aconst_null 将null值压入栈;
bipush和sipush 表示将单字节或者短整形的常量值压入操作数栈;
带ldc的表示将什么类型数据从常量池中压入到操作数栈;如:
ldc_w 将int或者flat或者string类型的数据压入到操作数栈;
ldc2_w 将long或者double类型的数据压入到操作数栈;
凡是带load的指令表示将某类型的局部变量数据压入到操作数栈的栈顶;如:
iload 表示将int类型的局部变量压入到操作数栈的栈顶;
aload 以a开头的表示将引用类型的局部变量压入到操作数栈的栈顶;
iload_1 将局部变量数组里面下标为1的int类型的数据压入到操作数栈;
iaload 将int型数组的指定索引的值压入到操作数栈;
凡是带有store指令的表示将操作数栈顶的某类型的值存入指定的局部变量中;如:
istore 表示将栈顶int类型的数据存入到指定的局部变量中;
istore_3 表示将栈int类型的数据存入到局部变量数组的下标为3的元素中;
pop 将栈顶数据弹出;pop2将栈顶的一个long或者double数据从栈顶弹出来;
dup 复制栈顶的数据并将复制的值也压入到栈顶;
dup2 复制栈顶一个long或者是double的数据并将复制的值也压入到栈顶;
swap 将栈最顶端的两个值互换;
iadd 将栈顶两个int型的数据相加然后将结果再次的压入到栈顶;
isub 将栈顶两个int型的数据相减然后将结果再次的压入到栈顶;
imul 将栈顶两个int型的数据相乘然后将结果再次的压入到栈顶;
idiv 将栈顶两个int型的数据相除然后将结果再次的压入到栈顶;
irem 将栈顶两个int型的数据取模运算然后将结果再次的压入到栈顶;
ineg 将栈顶的int数据取负将结果压入到栈顶;
iinc 将指定的int变量增加指定值(i++,i--,i+=2);
i2l 将栈顶int类型数据强制转换成long型将结果压入到栈顶;
lcmp 将栈顶两long型数据的大小进行比较,并将结果(1,0,-1)压入栈顶;
以if开头的指令都是跳转指令;
tableswitch、lookupswitch 表示用switch条件跳转;
ireturn 从当前方法返回int型数据;
getstatic 获取指定类的静态域,将将结果压入到栈顶;
putstatic 为指定的类的静态域赋值;
getfield 获取指定类的实例变量,将结果压入到栈顶;
putfield 为指定类的实例变量赋值;
invokevirtual 调用实例方法;
invokespacial 调用超类构造方法,实例初始化方法,私有方法;
invokestatic 调用静态方法;
invokeinterface 调用接口方法;
new 创建一个对象,并将其引用压入到栈顶;
newarray 创建一个原始类型的数组,并将其引用压入到栈顶;
arraylength 获得一个数组的长度,将将结果压入到栈顶;
athrow 将栈顶的异常抛出;
checkcast 检验类型转换,转换未通过,将抛出ClassCastException.
instanceof 检验对象是否是指定的类的实例,如果是将1压入栈顶,否则将0压入栈顶
monitorenter 获得对象的锁,用于同步方法或同步块
monitorexit 释放对象的锁,用于同步方法或同步块
ifnull 为null时跳转
ifnonnull 不为null时跳转
字节码指令如何工作?
所有字节码指令都在Java虚拟机规范的第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对象而不会出现问题。ClassWriter和MethodWriter类不是 线程安全的,即几个并发线程不能生成单个类(但是,当然,如果每个线程使用自己的ClassWriter实例,则多个线程可以并发生成不同的类)。为了通过使用多个并发线程生成单个类,应该使用委托给普通ClassWriter和MethodWriter实例的ClassVisitor和MethodVisitor实例,并且它们的方法都是同步的。
更一般地说,ClassVisitor和MethodVisitor实现(如ClassWriter)不必是线程安全的。但是,只要在它们前面使用同步类适配器,就可以使非线程安全访问者成为线程安全的。-
ASM 提供了两种编程模型
- Core API,提供了基于事件形式的编程模型。该模型不需要一次性将整个类的结构读取到内存中,因此这种方式更快,需要更少的内存。但这种编程方式难度较大。
- Tree API,提供了基于树形的编程模型。该模型需要一次性将一个类的完整结构全部读取到内存当中,所以这种方法需要更多的内存。这种编程方式较简单。
- Core API 中操纵字节码的功能基于 ClassVisitor 接口。这个接口中的每个方法对应了 class 文件中的每一项。Class 文件中的简单项的访问使用一个单独的方法,方法参数描述了这个项的内容。而那些具有任意长度和复杂度的项,使用另外一类方法,这类方法会返回一个辅助的 Visitor 接口,通过这些辅助接口的对象来完成具体内容的访问。例如 visitField 方法和 visitMethod 方法,分别返回 FieldVisitor 和 MethodVisitor 接口的对象。
- ASM 提供了三个基于 ClassVisitor 接口的类来实现 class 文件的生成和转换:
- ClassReader:ClassReader 解析一个类的 class 字节码,该类的 accept 方法接受一个 ClassVisitor 的对象,在 accept 方法中,会按上文描述的顺序逐个调用 ClassVisitor 对象的方法。它可以被看做事件的生产者。
- ClassAdapter:ClassAdapter 是 ClassVisitor 的实现类。它的构造方法中需要一个 ClassVisitor 对象,并保存为字段 protected ClassVisitor cv。在它的实现中,每个方法都是原封不动的直接调用 cv 的对应方法,并传递同样的参数。可以通过继承 ClassAdapter 并修改其中的部分方法达到过滤的作用。它可以看做是事件的过滤器。
- ClassWriter:ClassWriter 也是 ClassVisitor 的实现类。ClassWriter 可以用来以二进制的方式创建一个类的字节码。对于 ClassWriter 的每个方法的调用会创建类的相应部分。例如:调用 visit 方法就是创建一个类的声明部分,每调用一次 visitMethod 方法就会在这个类中创建一个新的方法。在调用 visitEnd 方法后即表明该类的创建已经完成。它最终生成一个字节数组,这个字节数组中包含了一个类的 class 文件的完整字节码内容 。可以通过 toByteArray 方法获取生成的字节数组。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生成类的字节码
*/
public class GeneratorClass {
public static void main(String[] args) throws IOException {
//① ClassReader:该类用来解析编译过的class字节码文件。
//② ClassWriter:该类用来重新构建编译后的类,比如说修改类名、属性以及方法,甚至可以生成新的类的字节码文件。
//③ ClassAdapter:该类也实现了ClassVisitor接口,它将对它的方法调用委托给另一个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:类的访问标识
// name:类名称
// signature:类签名,如果类不是通用类,并且不扩展或实现泛型类或接口,则可能为null。
// superName:超类名称,如果是接口或超类为Object则可能为null
// interfaces:类实现的接口名称列表
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:字段访问标识
// 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:方法访问标识
// name:方法名称
// desc:方法描述
// signature:方法签名,若方法参数、返回类型和异常没有使用泛型则可能为null
// exceptions:方法的异常名,可能为null
cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "compareTo",
"(Ljava/lang/Object;)I", null, null).visitEnd();
//使cw类已经完成
cw.visitEnd();
//将cw转换成字节数组写到文件里面去
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:类的访问标识
// name:类名称
// signature:类签名,如果类不是通用类,并且不扩展或实现泛型类或接口,则可能为null。
// superName:超类名称,如果是接口或超类为Object则可能为null
// interfaces:类实现的接口名称列表
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:字段访问标识
// 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:方法访问标识
// name:方法名称
// desc:方法描述
// signature:方法签名,若方法参数、返回类型和异常没有使用泛型则可能为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: [email protected]
* 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;
// 是否是数组
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
*
* @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
*
* @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: [email protected]
* 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 extends LinkedHashMap implements Iterable
* 签名: Ljava/util/LinkedHashMap;Ljava/lang/Iterable;
* 使用方法:
* String s = utils.genClassSimpleSign(new String[]{"T", "U"},
* new LinkedHashMap() {{
* put(LinkedHashMap.class, new String[]{"T","U"});
* }},
* new LinkedHashMap() {{
* put(Iterable.class, new String[]{"T"});
* }}
* );
*
* @param classPlasticity
* @param superClassPlasticity
* @param interface_plasticity
* @return
*/
public static String genClassSimpleSign(
List classPlasticity,
ClassType superClassPlasticity,
List 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 interface_plasticity, List classPlasticity) {
interfaceSuperClassPlasticity(sign, interface_plasticity);
}
// 超类范型签名
private static void superClassPlasticity(StringBuilder sign, ClassType superClassPlasticity, List classPlasticity) {
if (null == superClassPlasticity) {
sign.append(class2SignStr(Object.class)).append(SEMICOLON);
return;
}
interfaceSuperClassPlasticity(sign, Arrays.asList(superClassPlasticity));
}
// 接口范型签名
private static void interfaceSuperClassPlasticity(StringBuilder sign, List 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 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 转成 类签名
*
* @param clazz
* @return
*/
public static String class2SignStr(Class> clazz) {
return CLASS_START + class2TypeStr(clazz);
}
/**
* class 转成用/分割的类全路径
*
* @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 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 argsTypes, List 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 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;
}
/**
* 生成参数签名
* (TT;TU;)
*
* (ILjava/lang/String;[[Lcom/sosnoski/generics/FileInfo;)V
* void mmm(int x, String y, FileInfo[][] z)
*
* @param types 参数类型,参数类型范型
* @param classPlasticity
* @return
*/
private static MethodDesc genMethodArgsTypeSimpleSign(MethodDesc typeDesc, List types, List 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 字节码生成工具类
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: [email protected]
* 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/util/List;",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(
// 字节码版本
int version,
// 类权限修饰符
int accessModifier,
// 类名
String className,
// 超类
Class superClass,
// 接口列表
List interfacesClass,
// 类中所有的范型列表,eg:K,V
List classPlasticity,
// 超类范型
ClassType superClassPlasticity,
// 接口范型
List 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 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 argsTypes, List 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;
}
/**
* 静态变量入栈
*
* @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));
}
/**
* 调用静态方法
*
* @param adapter
* @param methodDesc 返回值 方法名 (参数列表) 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));
}
/**
* 调用对象方法
*
* @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));
}
/**
* 调用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)");
}
/**
* 调用构造方法
*
* @param adapter
*/
public void allocateConstructor(GeneratorAdapter adapter, Class classType) {
adapter.invokeConstructor(Type.getType(classType), org.objectweb.asm.commons.Method.getMethod("void ()"));
}
/**
* 创建方法域内的局部变量
*
* @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);
}
/**
* 生成默认无参的构造方法,调用超类的构造方法
*
* @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 ()"));
}
/**
* 生成默认无参的构造方法,调用超类的构造方法
*
* @param adapter
* @param superClass 超类
*/
public void genDefaultConstructor(GeneratorAdapter adapter, String superClass) {
adapter.loadThis();
Type type = Type.getType(superClass);
logger.debug(": super class:" + type.getDescriptor());
adapter.invokeConstructor(type, org.objectweb.asm.commons.Method.getMethod("void ()"));
}
/**
* 结束方法
*
* @param adapter
*/
public void returnAndEndMethod(GeneratorAdapter adapter) {
// 缺少returnValue 将导致
// 错误: 无法初始化主类 Abc
//原因: java.lang.VerifyError: Control flow falls through code end
//Exception Details:
// Location:
// Abc.main([Ljava/lang/String;)V @8:
// Reason:
// Error exists in the bytecode
// Bytecode:
// 0000000: b200 2212 24b6 002a
adapter.returnValue();
//如何让ASM为我计算visitMaxs?
//调用ClassWriter的构造函数时,请使用COMPUTE_MAXS标志。
// 您还必须包含visitMaxs方法调用,但忽略您给出的值,因此visitMaxs(0,0)没问题。
adapter.visitMaxs(0, 0);
//缺少这句将导致java.lang.VerifyError:
// (class: Abc, method: main signature: ([Ljava/lang/String;)V) Stack size too large
adapter.endMethod();
}
/**
* 创建Setter
*
* @param className
* @param fieldType
* @param fieldName
* @param classPlasticity
*/
public void createSetter(String className, ClassType fieldType, String fieldName, List 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);
}
/**
* 创建Getter
*
* @param className
* @param fieldType
* @param fieldName
* @param classPlasticity
*/
public void createGetter(String className, ClassType fieldType, String fieldName, List 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: [email protected]
* 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 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,"",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 extends LinkedHashMap implements Iterable {
private static int a;
private static final double b = 1000.01D;
private Map 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 iterator() {
return null;
}
public Integer compareTo(Integer var1) {
return var1;
}
public K getA(V var1) {
return null;
}
public List 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文件路径,执行
| => java Abc
# 说明生成成功而且字节码没问题
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: [email protected]
* 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 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,"",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文件路径,执行
# 说明生成成功而且字节码没问题
| => java Bcd
Hello Bcd!