java使用asm生成简单类


import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.commons.LocalVariablesSorter;
import org.apache.curator.utils.PathUtils;
import org.apache.dubbo.common.utils.IOUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;

import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_MAXS;
import static jdk.internal.org.objectweb.asm.Opcodes.*;


public class AsmMain {
    public static void main(String[] args) throws Exception {
        testCreateAClass();
    }


    public static void testCreateAClass()throws Exception{

        //新建一个类生成器,COMPUTE_FRAMES,COMPUTE_MAXS这2个参数能够让asm自动更新操作数栈
        ClassWriter cw=new ClassWriter(COMPUTE_FRAMES|COMPUTE_MAXS);
        //生成一个public的类,类路径是com.study.Human
        cw.visit(V1_8,ACC_PUBLIC,"com/study/Human",null,"java/lang/Object",null);

        //生成默认的构造方法: public Human()
        MethodVisitor mv=cw.visitMethod(ACC_PUBLIC,"<init>","()V",null,null);
        mv.visitVarInsn(ALOAD,0);
        mv.visitMethodInsn(INVOKESPECIAL,"java/lang/Object","<init>","()V",false);
        mv.visitInsn(RETURN);
        mv.visitMaxs(0,0);//更新操作数栈
        mv.visitEnd();//一定要有visitEnd

        //生成成员变量
        //1.生成String类型的成员变量:private String name;
        FieldVisitor fv= cw.visitField(ACC_PRIVATE,"name","Ljava/lang/String;",null,null);
        fv.visitEnd();//不要忘记end
        //2.生成Long类型成员:private long age
        fv=cw.visitField(ACC_PRIVATE,"age","J",null,null);
        fv.visitEnd();

        //3.生成Int类型成员:protected int no
        fv=cw.visitField(ACC_PROTECTED,"no","I",null,null);
        fv.visitEnd();

        //4.生成静态成员变量:public static long score
        fv=cw.visitField(ACC_PUBLIC+ACC_STATIC,"score","J",null,null);

        //5.生成常量:public static final String real_name = "Sand哥"
        fv=cw.visitField(ACC_PUBLIC+ACC_STATIC+ACC_FINAL,"real_name","Ljava/lang/String;",null,"Sand哥");
        fv.visitEnd();

        //6.生成成员方法greet
        mv=cw.visitMethod(ACC_PUBLIC,"greet","(Ljava/lang/String;)I",null,null);
        mv.visitCode();
        mv.visitIntInsn(ALOAD,0);
        mv.visitIntInsn(ALOAD,1);

        //6.1 调用静态方法 System.out.println("Hello");
        mv.visitFieldInsn(GETSTATIC,"java/lang/System","out","Ljava/io/PrintStream;");
//        mv.visitLdcInsn("Hello");//加载字符常量
        mv.visitIntInsn(ALOAD,1);//加载形参
        mv.visitMethodInsn(INVOKEVIRTUAL,"java/io/PrintStream","println","(Ljava/lang/String;)V",false);//打印形参
        //6.2 创建局部变量
        LocalVariablesSorter lvs=new LocalVariablesSorter(ACC_PUBLIC,"(Ljava/lang/String;)I",mv);
        //创建ArrayList 对象
        //new ArrayList ,分配内存不初始化
        mv.visitTypeInsn(NEW,"java/util/ArrayList");
        mv.visitInsn(DUP);//压入栈
        //弹出一个对象所在的地址,进行初始化操作,构造函数默认为空,此时栈大小为1(到目前只有一个局部变量)
        mv.visitMethodInsn(INVOKESPECIAL,"java/util/ArrayList","<init>","()V",false);

        int time=lvs.newLocal(Type.getType(List.class));

        mv.visitVarInsn(ASTORE,time);
        mv.visitVarInsn(ALOAD,time);

        //创建StringBuilder对象
        mv.visitTypeInsn(NEW,"java/lang/StringBuilder");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL,"java/lang/StringBuilder","<init>","()V",false);

        //这里需要注意在lvs.newLocal的时候使用Type.geteType("类路径") 会报错,需要改成Type.geteType("XXX.class“)的方式
        time=lvs.newLocal(Type.getType(StringBuilder.class));
        mv.visitVarInsn(ASTORE,time);
        mv.visitVarInsn(ALOAD,time);
        mv.visitLdcInsn("Hello java asm StringBuilder");
        mv.visitMethodInsn(INVOKEVIRTUAL,"java/lang/StringBuilder","append","(Ljava/lang/String;)Ljava/lang/StringBuilder;",false);
        mv.visitMethodInsn(INVOKESTATIC,"java/lang/System","nanoTime","()J",false);
        time=lvs.newLocal(Type.LONG_TYPE);
        mv.visitVarInsn(LSTORE,time);
        mv.visitLdcInsn(10);
        mv.visitLdcInsn(11);
        mv.visitInsn(IADD);
        mv.visitInsn(IRETURN);
        mv.visitMaxs(0,0);
        mv.visitEnd();
        //生成静态方法
        mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "staticMethod", "(Ljava/lang/String;)V", null, null);
        //生成静态方法中的字节码指令
        mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
        mv.visitLdcInsn("Hello Java Asm!");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
        //设置必要的类路径
        String path= "Human.class";
        //获取类的byte数组
        byte[] classByteData=cw.toByteArray();
        //把类数据写入到class文件,这样你就可以把这个类文件打包供其他的人使用
        IOUtils.write(new ByteArrayInputStream(classByteData),new FileOutputStream(path));
        System.err.println("类生成的位置:"+path);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值