Fastjson源码分析—ASM的作用和实现(2)

2021SC@SDUSC
上一篇介绍了Java字节码文件的格式、ASM的定义和如何在Fastjson中开启/关闭ASM,这篇内容介绍ASM在Fastjson中的具体实现。

在IDEA中查看

在IDEA中下载ASM Bytecode Outline插件
在这里插入图片描述
下载完成后,选择你想查看的文件,右键,点击Show Bytecode outline
在这里插入图片描述
现在就可以查看该文件的class文件反编译后生成的文件。这样做的好处是,当你没有源文件而只有class文件时,可以通过这种方式查看其中的变量和方法,便于进行asm的修改。

ASM关键类的分析

ClassReader

这是ClassReader的方法,上一篇我们分析了accept方法的实现,它的作用是接受一个实现了visitor接口的对象作为参数,调用其中的visit方法实现对字节码的修改。
在这里插入图片描述

构造方法用于一个输入流(class文件),分析字节码并用于生成表示字节码的树,便于accept方法调用其中的方法。
剩下的5个成员方法都是用来接受实现了visitor的类的class文件,分析其中的变量和方法。这几个方法都用于给accept方法调用。

ClassWriter

ASM 的最终的目的是生成可以被正常装载的 class 文件,因此其框架结构为客户提供了一个生成字节码的工具类 —— ClassWriter。它实现了 ClassVisitor接口,而且含有一个 toByteArray()函数,返回生成的字节码的字节流,将字节流写回文件即可生产调整后的 class 文件。一般它都作为职责链的终点,把所有 visit 事件的先后调用(时间上的先后),最终转换成字节码的位置的调整(空间上的前后)

这里我们关键查看它的toByteArray方法,看看如何生成class文件

    public byte[] toByteArray() {
        int size = 24 + 2 * this.interfaceCount;
        int nbFields = 0;

        FieldWriter fb;
        for(fb = this.firstField; fb != null; fb = fb.next) {
            ++nbFields;
            size += fb.getSize();
        }

        int nbMethods = 0;

        MethodWriter mb;
        for(mb = this.firstMethod; mb != null; mb = mb.next) {
            ++nbMethods;
            size += mb.getSize();
        }

        int attributeCount = 0;
        size += this.pool.length;
        ByteVector out = new ByteVector(size);
        out.putInt(-889275714).putInt(this.version);
        out.putShort(this.index).putByteArray(this.pool.data, 0, this.pool.length);
        int mask = 393216;
        out.putShort(this.access & ~mask).putShort(this.name).putShort(this.superName);
        out.putShort(this.interfaceCount);

        for(int i = 0; i < this.interfaceCount; ++i) {
            out.putShort(this.interfaces[i]);
        }

        out.putShort(nbFields);

        for(fb = this.firstField; fb != null; fb = fb.next) {
            fb.put(out);
        }

        out.putShort(nbMethods);

        for(mb = this.firstMethod; mb != null; mb = mb.next) {
            mb.put(out);
        }

        out.putShort(attributeCount);
        return out.data;
    }

可以看到,该方法生成了一个FieldWriter对象fb用于写变量,MethodWriter对象mb用于写方法,还生成了一个ByteVector向量out用于储存待生成的class文件的相关信息。紧接着fb和mb分别对out对象执行put方法,将out对象保存在自身的数据结构中。最后,返回out对像的data字段,作为class文件的二进制代码。

除此之外,我们再研究一下visit方法

public void visit(int version, int access, String name, String superName, String[] interfaces) {
        this.version = version;
        this.access = access;
        this.name = this.newClassItem(name).index;
        this.thisName = name;
        this.superName = superName == null ? 0 : this.newClassItem(superName).index;
        if (interfaces != null && interfaces.length > 0) {
            this.interfaceCount = interfaces.length;
            this.interfaces = new int[this.interfaceCount];

            for(int i = 0; i < this.interfaceCount; ++i) {
                this.interfaces[i] = this.newClassItem(interfaces[i]).index;
            }
        }

    }

介绍一下该方法的各个参数:

  • version:表示当前类的版本信息。我的Java版本是8,该变量取值为Opcodes.V1_8
  • access:表示访问标识信息。
  • name:表示当前类的名字,格式是Internal Name的形式
  • signature:表示当前类的泛型信息。当前接口无泛型信息,所以值为null
  • superName:父类名称,Internal Name形式
  • interfaces:表示当前类实现了哪些接口

这里,介绍一下Internal Name:在java文件,我们使用Java语言编写代码,类名的形式是Fully Qualified Class Name,例如java.lang.String;然而在class文件中,类名的形式称之为Internal Name,例如java/lang/String。这种转换实际上就是把.字符改成/字符。

总结

这两篇介绍了Fastjson中ASM的实现,具体分析了ASM的各个类和方法,这里总结一下ASM的执行流程:
1.ClassReader 读取字节码到内存中,生成用于表示该字节码的内部表示的树,ClassReader 对应于访问者模式中的元素
2.组装 ClassVisitor 责任链,这一系列 ClassVisitor 完成了对字节码一系列不同的字节码修改工作,对应于访问者模式中的访问者 Visitor
3.然后调用 ClassReader#accept() 方法,传入 ClassVisitor 对象,此 ClassVisitor 是责任链的头结点,经过责任链中每一个 ClassVisitor 的对已加载进内存的字节码的树结构上的每个节点的访问和修改
4.最后,在责任链的末端,调用 ClassWriter 这个 visitor 进行修改后的字节码的输出工作

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
fastjson是一款Java语言编写的高性能JSON处理库,其主要特点是速度快、内存占用低、功能强大、易于使用。下面就简单介绍一下fastjson源码分析。 1. 核心架构 fastjson的核心架构包括JSONReader、JSONWriter、JSONLexer、JSONParser、JSONScanner、JSONSerializer、JSONDeserializer等模块。其中,JSONLexer和JSONScanner是fastjson的词法分析器,JSONParser是解析器,JSONSerializer和JSONDeserializer是序列化和反序列化实现。 2. 序列化和反序列化 fastjson的序列化和反序列化实现主要基于Java的反射机制和ASM字节码生成技术。在序列化时,fastjson会根据Java对象的类型信息来生成相应的序列化代码,并将序列化后的数据输出到JSONWriter中。在反序列化时,fastjson根据JSON数据的类型信息来生成相应的反序列化代码,并将反序列化后的Java对象输出到JSONDeserializer中。 3. 性能优化 fastjson在性能上有很多优化,其中最重要的是使用了预编译技术,将JSON字符串解析为Java对象时,fastjson会对JSON字符串进行预编译,生成一个解析器,以提高解析效率。此外,fastjson还使用了缓存技术,将解析器和序列化器缓存起来,以便重复使用,从而减少了对象的创建和销毁所带来的开销。 4. 使用场景 fastjson广泛应用于互联网领域,如阿里巴巴、淘宝、天猫等都在使用fastjson来处理JSON数据。fastjson还支持多种数据格式的解析和序列化,如XML、CSV等。 以上是fastjson源码分析的简单介绍,相信大家对fastjson有了更深入的了解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值