谈谈fastjson反序列方法JSON.parseObject(String…
2018-09-01 05:41:52来源:博客园 阅读 ()
fastjson这一工具包帮助我们进行java对象和json格式的字符串之间的相互转换。对象到字符串的过程,我们称之为序列化;反之,我们称为反序列化。
现在我们就来谈谈fastjson提供的反序列化方法,本篇只讨论按照指定的字节码返回相应对象的的反序列化方法,该方法有多种重载形式,按照重叠构造的模式设计。常用的入口为:JSON.parseObject(String text, Class<T> clazz),其调用链为:
JSON.parseObject(String text, Class<T> clazz) --> parseObject(String text, Class<T> clazz, Feature... features) --> parseObject(String input, Type clazz, ParserConfig config, int featureValues, Feature... features) --> parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor, int featureValues, Feature... features)
这样最终实际调用的方法及其参数值为:parseObject(input, clazz, ParserConfig.getGlobalInstance(), null, DEFAULT_PARSER_FEATURE, new Feature[0])。
我们关注下ParserConfig.getGlobalInstance(),每次调用返回同一个ParserConfig对象。这样其实保证了以JSON.parseObject(String text, Class<T> clazz)为入口的场景下,ParserConfig对象的全局唯一,即所谓的单例。
我们看看ParserConfig对象在fastjson反序列化过程中的作用:
作用一:维护了常用类型和反序列化器之间的对应关系,存放到IdentityHashMap<Type, ObjectDeserializer>中,并可通过getDeserializer(Type type)方法获得对象反序列化器ObjectDeserializer;对于非预定义好的类型,拿到该类型的反序列化器的同时,并建立该类型和相应反序列化器的对应关系,存放到IdentityHashMap<Type, ObjectDeserializer>中,以便后续直接使用;
作用二:创建字段反序列化器FieldDeserializer,而这些FieldDeserializer会维护到ObjectDeserializer的IdentityHashMap<String, FieldDeserializer>中,其中key为字段名称。
重点关注FieldDeserializer的生成,通过源码分析,通常情况下会调用ASMDeserializerFactory.getInstance().createFieldDeserializer(parserConfig, clazz, fieldInfo)生成字段反序列化器。
if (fieldClass == int.class || fieldClass == long.class || fieldClass == String.class) {
return createStringFieldDeserializer(mapping, clazz, fieldInfo);
}
通过上面createFieldDeserializer中的源码可以看出,针对int、long和String类型做了特殊处理,进一步分析发现其内部利用asm字节码增加技术对IntegerFieldDeserializer、LongFieldDeserializer以及StringFieldDeserializer做了扩展,动态生成了新的类。
类名为:String name = "Fastjson_ASM__Field_" + clazz.getSimpleName();
name += "_" + fieldInfo.getName() + "_" + seed.incrementAndGet();(注意seed此种场景下是单例的)
该类主要是新增了setValue()方法,应该是用来对字段进行赋值操作的(PS:关于对象序列化和字段序列化器的内部处理逻辑有机会可进一步分析研究)
综上:针对保留了永久代的jvm,对于如上三种类型的字段,在创建FieldDeserializer时会动态生成新的类,造成jvm加载的类的数目上升,永久代内存的增加。当然通常情况,一个项目中需要反序列化的类是有限的,并且因为常用情况下ParseConfig是单例,相应字段对应的字段序列化器类生成一份后就不在重复生成了,永久代内存通常情况下也就不会溢出。
JSON.parseObject ( reqMsg, ReqMsgDto.class, new ParserConfig() , JSONObject.DEFAULT_PARSER_FEATURE )
但若如上进行api的调用,此种情况下ParserConfig不在全局唯一,就可能会持续不断的生成字段序列化器类,从而造成java.lang.OutOfMemoryError: PermGen space。此种场景下应将ParserConfig的实例作为类变量或者成员变量,以避免每次调用都会创建新的字段序列化类。
备注:fastjson源码分析基于1.1.37版本
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇:一个表单同时提交多条记录
- Dubbo 2.7.7 发布,FastJson 升级了! 2020-05-25
- LeetCode 面试题33. 二叉搜索树的后序遍历序列 2020-05-22
- LeetCode 105. 从前序与中序遍历序列构造二叉树 2020-05-22
- MapperReduce序列化自定义分区作业 2020-05-20
- 关于序列化的 10 几个问题,你顶得住不?.md 2020-05-19
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash