fastjson 问题:修改属性的类型后无法解析

mec1mxoz  于 5个月前  发布在  其他
关注(0)|答案(4)|浏览(48)
  • 项目第一次启动,调用 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
  • 想请教下有没有什么思路能定位出现这个问题的原因,现在是能是类型变了,重新启用项目才行。
twh00eeo

twh00eeo1#

猜测与jrebel的热部署功能及fastjson的运行机制有关。
首先提一下fastjson的缓存机制:假如clazz类在项目启用后曾经被序列化/反序列化过,fastjson会缓存一份clazz类对象专属的序列化器和反序列化器,里面包含了clazz类的方法、属性等元数据,以供之后的序列化和反序列化使用。
而jrebel的热部署功能会使得即使clazz类定义被修改后,内存中仍保留原本的clazz类的标识和状态。
因此在下一次序列化、反序列化时fastjson通过这些标识和状态会认为可以直接复用之前缓存下来的数据,此时就出现了真实clazz数据与fastjson缓存的clazz元数据对应不上的情况。
当你重新启用项目时,相当于手动清除了fastjson缓存好的数据,所以可以生效。

可以试试在修改了clazz类型之后,通过调用 SerializeConfigParseConfigput(clazz.class, null) 方法,用null值取代原有的缓存,强制重新生成序列化器和反序列化器。

wfypjpf4

wfypjpf42#

fastjson为了快速处理,缓存了对象的类型数据和反射相关数据,你改了类型,缓存的数据就对不上了。

改了类型就重启一下再debug

frebpwbc

frebpwbc3#

清除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的缓存无法刷新问题

xlpyo6sf

xlpyo6sf4#

还有个思路,可以在开发环境,禁用asm功能

SerializeConfig.getGlobalInstance().setAsmEnable(false);

相关问题