问题:修改属性的类型后无法解析
-
项目第一次启动,调用
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
- 想请教下有没有什么思路能定位出现这个问题的原因,现在是能是类型变了,重新启用项目才行。
猜测与jrebel的热部署功能及fastjson的运行机制有关。 首先提一下fastjson的缓存机制:假如clazz类在项目启用后曾经被序列化/反序列化过,fastjson会缓存一份clazz类对象专属的序列化器和反序列化器,里面包含了clazz类的方法、属性等元数据,以供之后的序列化和反序列化使用。 而jrebel的热部署功能会使得即使clazz类定义被修改后,内存中仍保留原本的clazz类的标识和状态。 因此在下一次序列化、反序列化时fastjson通过这些标识和状态会认为可以直接复用之前缓存下来的数据,此时就出现了真实clazz数据与fastjson缓存的clazz元数据对应不上的情况。 当你重新启用项目时,相当于手动清除了fastjson缓存好的数据,所以可以生效。
可以试试在修改了clazz类型之后,通过调用SerializeConfig和ParseConfig的put(clazz.class, null)方法,用null值取代原有的缓存,强制重新生成序列化器和反序列化器。
fastjson为了快速处理,缓存了对象的类型数据和反射相关数据,你改了类型,缓存的数据就对不上了。
改了类型就重启一下再debug
清除FastJson缓存的方法如下:
@RestController
@RequestMapping("/api")
public class SystemController {
@ApiOperation(value = "开发时清除缓存", notes = "用于开发使用JRebel时清除FastJson的对象解析Cache")
@RequestMapping(value = "/clearCache", method = RequestMethod.GET)
public String clearCache() {
SerializeConfig.getGlobalInstance().clearSerializers();
ParserConfig.getGlobalInstance().clearDeserializers();
return "";
}
}
调用该方法即可清除缓存。 可以参见我的博文:解决JRebel进行代码热加载时FastJson的JsonField的缓存无法刷新问题
还有个思路,可以在开发环境,禁用asm功能
SerializeConfig.getGlobalInstance().setAsmEnable(false);
清除FastJson缓存的方法如下:
@RestController @RequestMapping("/api") public class SystemController { @ApiOperation(value = "开发时清除缓存", notes = "用于开发使用JRebel时清除FastJson的对象解析Cache") @RequestMapping(value = "/clearCache", method = RequestMethod.GET) public String clearCache() { SerializeConfig.getGlobalInstance().clearSerializers(); ParserConfig.getGlobalInstance().clearDeserializers(); return ""; } }调用该方法即可清除缓存。 可以参见我的博文:解决JRebel进行代码热加载时FastJson的JsonField的缓存无法刷新问题
您好,请问在FastJson2中这两个类没有了,应该如何配置呢