jackson、fastjson、gson对比
反序列化实现区别
- jackson:反射+反射缓存、良好的stream支持、高效的内存管理
- fastjson:
- jvm虚拟机:通过ASM库运行时生成parser字节码,支持的field不能超过200个。参考:FastJson使用ASM反序列化。
- android虚拟机:反射的方式。
- gson:反射+反射缓存、支持部分stream、内存性能较差(gc问题)。
ASM
- ASM是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。
- ASM能够通过改造既有类,直接生成需要的代码。增强的代码是硬编码在新生成的类文件内部的,没有反射带来性能上的付出。
- ASM可以用来实现AOP。
反射性能
- 反射性能相对于对象直接访问性能相差两个数量级(百倍)。
- 反射很大一部分性能消耗在遍历Field。
- 反射缓存能够提高1个数量级的性能。
- 测试数据参考:link。
jackson特性
- 功能全面、强大:支持stream、databind、path功能。
- 安装包1.2M,运行时自身占用几百k内存,解析json时内存管理很高效。
- 实现了较全面、复杂的反射缓存功能,如下:
Gson特性
- 安装包143k,运行时自身占用不到100k内存,但解析json时占用内存较多。
- 通过反射做json的反序列化,缓存反射的Field做反射性能优化,简单直接。如下:
fastjson特性
- 在jvm虚拟机上使用ASM动态生成反序列化字节码,以此减少反射性能开销;会导致Perm区class增多。
- 在android平台使用反射的方式实现反序列化,而且性能较差;原因是android独有的dex字节码与java的.class字节码格式不兼容,无法使用ASM。
- fastjson在android平台性能很低;android平台更适合APT的方式生成代码,比如依赖注入库dagger2,性能很高。
移动端面临的问题
冷启动问题
- 由于dalvik、ART虚拟机无反射缓存时性能很差,第一次反序列化json会有很大的时间开销。参考:link。
资源占用问题
- jackson、gson对象会做反射缓存,占用堆空间,jackson比gson占用内存更大。
- 解决方案:jackson、gson对象使用单例模式做复用,使用软引用单利对象,允许java内存不够时回收这些内存。
- jackson支持stream的方式,做网络api的时候可以直接做输入流->Object的转换,优化性能,如下代码:
1 | @Get("/api/some/large/json/resource") |
gc问题
- gson反序列化/序列化json的时候内存管理不是太好,引发较多gc。