fastjson反序列化⽅法JSON.parseObject(Stringstr,Clas。。
。
fastjson这⼀⼯具包帮助我们进⾏java对象和json格式的字符串之间的相互转换。对象到字符串的过程,我们称之为序列化;反之,我们称为反序列化。
现在我们就来谈谈fastjson提供的反序列化⽅法,本篇只讨论按照指定的字节码返回相应对象的的反序列化⽅法,该⽅法有多种重载形式,按照重叠构造的模式设计。常⽤的⼊⼝为:JSON.parseObject(String text, Class<T> clazz),其调⽤链为:
JSON.parseObject(String text, Class<T> clazz) --> parseObject(String text, Class<T> clazz, features) -->
parseObject(String input, Type clazz, ParserConfig config, int featureValues, features) --> parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor, int featureValues, features)
这样最终实际调⽤的⽅法及其参数值为:parseObject(input, clazz, GlobalInstance(), null,
DEFAULT_PARSER_FEATURE, new Feature[0])。
我们关注下GlobalInstance(),每次调⽤返回同⼀个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的⽣成,通过源码分析,通常情况下会调⽤
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_" + SimpleName();
fastjson常用方法name += "_" + Name() + "_" + 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的实例作为类变量或者成员变量,以避免每次调⽤都会创建新的字段序列化类。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论