• 技术文章 >Java >java教程

    java字节码框架ASM操作字节码的方法浅析

    高洛峰高洛峰2017-01-23 10:23:51原创1154
    之前我们已经对ASM进行的详细的介绍,需要的朋友们可以点击这里:java字节码框架ASM的深入学习

    JVM的类型签名对照表

    java字节码框架ASM操作字节码的方法浅析

    php入门到就业线上直播课:进入学习

    比如,java方法是

    long f (int n, String s, int[] arr);

    对应的类型签名就是

    f (ILjava/lang/String;[I)J

    再比如,java方法是

    private void hi(double a, List<String> b);

    那对应的类型签名就是

    hi (DLjava/util/List;)V

    接下来可以利用ASM进行验证上述两个类型签名是否正确:

    public class Test {
     
     public static void main(String[] args) throws Exception {
     ClassPrinter printer = new ClassPrinter();
     //读取静态内部类Bazhang
     ClassReader cr = new ClassReader("Test$Bazhang");
     cr.accept(printer, 0);
     
     }
     
     //静态内部类
     static class Bazhang {
     
     public Bazhang(int a) {
     }
     
     private long f (int n, String s, int[] arr){
      return 0;
     }
     
     private void hi(double a, List<String> b){
     
     }
     }
     
     static class ClassPrinter extends ClassVisitor {
     
     public ClassPrinter() {
      super(Opcodes.ASM5);
     }
     
     @Override
     public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
      super.visit(version, access, name, signature, superName, interfaces);
      //打印出父类name和本类name
      System.out.println(superName + " " + name);
     }
     
     @Override
     public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
      //打印出方法名和类型签名
      System.out.println(name + " " + desc);
      return super.visitMethod(access, name, desc, signature, exceptions);
     }
     }
     
    }

    最后打印出来的内容:

    java/lang/Object Test$Bazhang
    <init> ()V
    f (ILjava/lang/String;[I)J
    hi (DLjava/util/List;)V

    验证了之前的正确性,其中可以看到默认构造函数也打印出来了。

    那么接下来干点有意思的事,我们往Bazhang类里新增和方法,就定为:

    public void newFunc(String str){
      
    }

    这个时候就需要用到ClassWriter了,用于拼接字节码,具体关于ClassReader、ClassVisitor、ClassWriter的文章可以查看这篇文章:ASM源码学习之ClassReader、ClassVisitor与ClassWriter详解

    public static void main(String[] args) throws Exception {
     ClassReader cr = new ClassReader(Bazhang.class.getName());
     ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
     
     cr.accept(cw, Opcodes.ASM5);
     
     MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "newFunc", "(Ljava/lang/String;)V", null, null);
     
     mv.visitInsn(Opcodes.RETURN);
     mv.visitEnd();
     
     // 获取生成的class文件对应的二进制流
     byte[] code = cw.toByteArray();
      
     //将二进制流写到out/下
     FileOutputStream fos = new FileOutputStream("out/Bazhang222.class");
     fos.write(code);
     fos.close();
     
    }

    这样就会在out/文件夹下生成Bazhang222.class:

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
     
    import java.util.List;
     
    class Test$Bazhang {
     Test$Bazhang() {
     }
     
     private long f(int n, String s, int[] arr) {
     return 0L;
     }
     
     private void hi(double a, List<String> b) {
     }
     
     public void newFunc(String var1) {
     }
    }

    结合之前整理的JVM指令集,使用ASM直接操作字节码也是没问题的,结尾附上ASM源码下载地址:http://forge.ow2.org/projects/asm/

    总结

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

    更多java字节码框架ASM操作字节码的方法浅析相关文章请关注PHP中文网!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    自己动手写 PHP MVC 框架:点击学习

    快速了解MVC架构、了解框架底层运行原理

    专题推荐:asm 字节码
    上一篇:JAVA中JVM的重排序详细介绍 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• Java数据结构之单链表与OJ题• 详细介绍Java正则表达式之单字符匹配和预定义字符• Java总结分享之反射、枚举、Lambda表达式• 实例详解Java顺序表和链表• 一文搞懂Java线程池实现原理
    1/1

    PHP中文网