`
15606915740
  • 浏览: 18482 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
文章分类
社区版块
存档分类
最新评论

通过spring asm 操作字节码生成属性get和set方法

阅读更多
   public static void strongClass() throws Exception{
        String myPath = "file:/D:/test/class/MyMain.class";
        System.out.println(myPath);
        byte[] cLassBytes = null;
        Path path = null;
        try {
            path = Paths.get(new URI(myPath));
            cLassBytes = Files.readAllBytes(path);
            System.out.println("========bytes size =======" + cLassBytes.length);
            //spring asm的包
            ClassReader cr = new ClassReader(cLassBytes);
            jdk.internal.org.objectweb.asm.ClassReader jcr = new jdk.internal.org.objectweb.asm.ClassReader(cLassBytes);
            //jdk rt.jar中的包
            ClassNode cn = new ClassNode();
            jcr.accept(cn,0);
            List<FieldNode> fields = cn.fields;
            //spring asm的包
            ClassWriter cw = new ClassWriter(cr,ClassWriter.COMPUTE_MAXS);
            cr.accept(cw, Opcodes.ASM5);
            MethodVisitor mv = null;
            for(FieldNode n : fields){
            String fieldName = n.name;
            String typeOf = n.desc;
                System.out.println(typeOf);
            // getMethod  StringUtils也是用spring core中的工具包
            String getMethodName = "get" + StringUtils.capitalize(fieldName);
                //第一个参数是方法的访问权限(public,private等)
                //第二个参数是方法名(<init>是构造函数的)
                //第三个参数是返回类型(()V是没有返回值)
                //第四个参数是和泛型相关的, 这里传入null表示该方法不是泛型方法
                //第五个参数指定方法声明可能抛出的异常。 这里无异常声明抛出
            mv = cw.visitMethod(ACC_PUBLIC, getMethodName, "()" + typeOf, null, null);
                //生成方法中的代码
            mv.visitCode();
            //调用visitVarInsn方法,生成aload指令, 将第0个本地变量(也就是this)压入操作数栈。
            mv.visitVarInsn(ALOAD, 0);
                //调用visiFieldInsn是将属性压入栈
            mv.visitFieldInsn(GETFIELD, "MyMain", fieldName, typeOf);
                //调用visitInsn方法,生成return指令, 方法返回
            mv.visitInsn(loadAndReturnOf(typeOf)[1]);
                //调用visitMaxs方法, 指定当前要生成的方法的最大局部变量和最大操作数栈
            mv.visitMaxs(2, 1);
                //最后调用visitEnd方法, 表示当前要生成的构造方法已经创建完成
            mv.visitEnd();

                String setMethodName = "set" + StringUtils.capitalize(fieldName);
                mv = cw.visitMethod(ACC_PUBLIC, setMethodName, "(" + typeOf + ")V", null, null);
                mv.visitCode();
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(loadAndReturnOf(typeOf)[0], 1);
                mv.visitFieldInsn(PUTFIELD, "MyMain", fieldName, typeOf);
                mv.visitInsn(RETURN);
                mv.visitMaxs(3, 3);
                mv.visitEnd();
            }
            byte[] bs = cw.toByteArray();
            cLassBytes = bs;
            System.out.println("========bytes size =======" + bs.length + cLassBytes.length);
            FileOutputStream fos = new FileOutputStream("E:/daemon1/MyMain.class");
            fos.write(cLassBytes);
            fos.flush();
            fos.close();
        } catch (IOException | URISyntaxException e) {
            e.printStackTrace();
        }
//        Class clz = new SynamicCompiler().defineClass("MyMain", cLassBytes, 0, cLassBytes.length);
//        Method method = clz.getMethod("getRedisUtil");
//        Method setMethod = clz.getMethod("setRedisUtil",RedisUtil.class);
//        Object obj = clz.newInstance();
//        setMethod.invoke(obj,new RedisUtil());
//        RedisUtil redisUtil = (RedisUtil) method.invoke(obj);
//        System.out.println(redisUtil);
       // Thread.sleep(5000);
    }
    //返回的都是字节码的指令,需要清楚字节码
    private static int[] loadAndReturnOf(String typeof) {
        System.out.println(typeof+"==??");
        if (typeof.equals("I") || typeof.equals("Z")) {
            return new int[]{ILOAD, IRETURN};
        } else if (typeof.equals("J")) {
            return new int[]{LLOAD, LRETURN};
        } else if (typeof.equals("D")) {
            return new int[]{DLOAD, DRETURN};
        } else if (typeof.equals("F")) {
            return new int[]{FLOAD, FRETURN};
        } else {
            return new int[]{ALOAD, ARETURN};
        }
    }
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics