- 项目第一次启动,调用
public static <T> T parseObject(String text, Class<T> clazz)
没有问题正常解析 - 修改
clazz
中的某个属性 String
改为 int
再次调用parseObject便会出现问题,调试到 FieldDeserializer.setValue(Object object, Object value)
中的 method.invoke(object, value)
- 部分信息如下
com.alibaba.fastjson.JSONException: set property error, com.....
Caused by: java.lang.reflect.InvocationTargetException
at com.zeroturnaround.jrebelbase.facade.w.throwWrappedNoSuchMethodError(SourceFile:179)
at com.zeroturnaround.jrebelbase.facade.w.checkMethodRemoved(SourceFile:200)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.alibaba.fastjson.parser.deserializer.FieldDeserializer.setValue(FieldDeserializer.java:110)
... 99 more
Caused by: java.lang.NoSuchMethodError: com.test.saas.integration.dto.SmartBoxDto.setiErrorCode(I)V
... 103 more
- 貌似只有在这个项目里这样,换成Gson则没有这个问题
- 开发中使用了jrebel
- 想请教下有没有什么思路能定位出现这个问题的原因,现在是能是类型变了,重新启用项目才行。
4条答案
按热度按时间twh00eeo1#
猜测与jrebel的热部署功能及fastjson的运行机制有关。
首先提一下fastjson的缓存机制:假如clazz类在项目启用后曾经被序列化/反序列化过,fastjson会缓存一份clazz类对象专属的序列化器和反序列化器,里面包含了clazz类的方法、属性等元数据,以供之后的序列化和反序列化使用。
而jrebel的热部署功能会使得即使clazz类定义被修改后,内存中仍保留原本的clazz类的标识和状态。
因此在下一次序列化、反序列化时fastjson通过这些标识和状态会认为可以直接复用之前缓存下来的数据,此时就出现了真实clazz数据与fastjson缓存的clazz元数据对应不上的情况。
当你重新启用项目时,相当于手动清除了fastjson缓存好的数据,所以可以生效。
可以试试在修改了clazz类型之后,通过调用
SerializeConfig
和ParseConfig
的put(clazz.class, null)
方法,用null值取代原有的缓存,强制重新生成序列化器和反序列化器。wfypjpf42#
fastjson为了快速处理,缓存了对象的类型数据和反射相关数据,你改了类型,缓存的数据就对不上了。
改了类型就重启一下再debug
frebpwbc3#
清除FastJson缓存的方法如下:
调用该方法即可清除缓存。
可以参见我的博文: 解决JRebel进行代码热加载时FastJson的JsonField的缓存无法刷新问题
xlpyo6sf4#
还有个思路,可以在开发环境,禁用asm功能
SerializeConfig.getGlobalInstance().setAsmEnable(false);