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

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版本

原文地址:https://www.cnblogs.com/yooung/p/9563445.html

时间: 2024-08-28 17:51:01

谈谈fastjson反序列方法JSON.parseObject(String text, Class<T> clazz)--来源于生产实践的相关文章

Android FastJson与不规范JSON引发的血案

去公司实习了,没多少时间更博客了,距离上一篇博客也有一个来月了.看标题,应该可以看出,这篇文章是讲一个坑,以及如何填坑. 坑是什么?有两个坑,其一是fastjson的bug,其二是不规范的json字符串.如何填坑,不要着急,后文详细说明. 首先,我们看一个json字符串 { "doubleParam": 4.875, "floatParam": 2.76, "extra": { "doubleParam": 12.23, &q

fastjson 使用方法

Fastjson介绍 Fastjson是一个Java语言编写的JSON处理器. 1.遵循http://json.org标准,为其官方网站收录的参考实现之一. 2.功能qiang打,支持JDK的各种类型,包括基本的JavaBean.Collection.Map.Date.Enum.泛型. 3.无依赖,不需要例外额外的jar,能够直接跑在JDK上. 4.开源,使用Apache License 2.0协议开源.http://code.alibabatech.com/wiki/display/FastJ

JSON.parseobject()和JSON.parseArray()区别

JSON.parseArray(): 这个方法的作用就是将json格式的数据转换成数组格式. 假设有Person这个类,有json类型数据jsonStr = [{"name":"张三","age":"1"},{"name":"李四","age":"4"}],那么List lists = json.parseArray(jsonStr, Person

android fastjson使用方法 fastjson教程

OK.由于因为数据加密,还有网络请求的问题,需要把JSON解析从后台Service中转移到前台UI线程来解析.所以,我开发的时候极大 的考虑了json解析的速度.不然耗时太厉害的话UI线程卡顿.会让界面看起来卡一下,卡一下的. package com.commons.utils.json; import com.tencent.stat.common.User; import org.apache.commons.lang.StringUtils; import java.security.Pr

如何使用fastJson来解析JSON格式数据和生成JSON格式数据

由于项目用到了JSON格式的数据,在网上搜索到了阿里的fastjson比较好用,特此记录fastjson用法,以备以后查询之用. decode: 首先创建一个JSON解析类: public class JsonParser { private int devid; public int getDevid() { return devid; } public void setDevid(int devid) { this.devid = devid; } } 在需要用到解析的地方创建一个对应的对象

JSON.parseObject 和 JSON.toJSONString

JSON.parseObject,是将Json字符串转化为相应的对象:JSON.toJSONString则是将对象转化为Json字符串.在前后台的传输过程中,Json字符串是相当常用的,这里就不多介绍其功能了,直接举一下应用的小例子,帮助理解这两个方法的用法. 首先用maven引入fastjson: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.ap

fastJson顺序遍历JSON字段

fastJson在把json格式的字符串转换成JSONObject的时候,使用的是HashMap,所以排序规则是根据HASH值排序的,如果想要按照字符串顺序遍历JSON属性,需要在转换的时候指定使用LinkedHashMap代替HashMap. public static void main(String[] args) { String jsonStr = "{\"size\":\"7.5\",\"width\":\"M (

JSON对象和字符串之间的相互转换JSON.stringify(obj)和JSON.parse(string)

在Firefox,chrome,opera,safari,ie9,ie8等高级浏览器直接可以用JSON对象的stringify()和parse()方法. JSON.stringify(obj)将JSON转为字符串.JSON.parse(string)将字符串转为JSON格式: var a={"name":"tom","sex":"男","age":"24"}; var aToStr =

用fastjson框架解析Json数据工具类

在Android应用开发中,APP端与server交互的数据一般是json格式的数据,那么为了方便操作,我们通常会用json解析框架来帮助我们进行数据操作.经常使用的有Gjson和fastjson框架.在项目中用到了fastjson解析数据,当然前提是要准备要对应的jar包工具,把工具类(主要是json数据与实体bean之间的转换操作)贴出来方便以后使用: public class FastJsonTools { /** * 用fastjson 将json字符串解析为一个 JavaBean *