java json.parse_谈谈fastjson反序列方法JSON.parseObject(String text, Class<T> clazz)--来源于生产实践...

fastjson这一工具包帮助我们进行java对象和json格式的字符串之间的相互转换。对象到字符串的过程,我们称之为序列化;反之,我们称为反序列化。

现在我们就来谈谈fastjson提供的反序列化方法,本篇只讨论按照指定的字节码返回相应对象的的反序列化方法,该方法有多种重载形式,按照重叠构造的模式设计。常用的入口为:json.parseobject(string text, class clazz),其调用链为:

json.parseobject(string text, class clazz) --> parseobject(string text, class 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 clazz)为入口的场景下,parserconfig对象的全局唯一,即所谓的单例。

我们看看parserconfig对象在fastjson反序列化过程中的作用:

作用一:维护了常用类型和反序列化器之间的对应关系,存放到identityhashmap中,并可通过getdeserializer(type type)方法获得对象反序列化器objectdeserializer;对于非预定义好的类型,拿到该类型的反序列化器的同时,并建立该类型和相应反序列化器的对应关系,存放到identityhashmap中,以便后续直接使用;

作用二:创建字段反序列化器fielddeserializer,而这些fielddeserializer会维护到objectdeserializer的identityhashmap中,其中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 )

70093c5da30fc82df79fdfd78ac2671a.png

但若如上进行api的调用,此种情况下parserconfig不在全局唯一,就可能会持续不断的生成字段序列化器类,从而造成java.lang.outofmemoryerror: permgen space。此种场景下应将parserconfig的实例作为类变量或者成员变量,以避免每次调用都会创建新的字段序列化类。

af14228302d61038b9913ef62c139734.png

备注:fastjson源码分析基于1.1.37版本

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值