线上异常描述
2016年3月初的某次上线后,发现【手动版5008建议详情】日志报异常 jsonMappingException: Can not create bean serializer for Object.class
经过google后得知该异常是因为jasckson不能转化没有公开属性的对象,比如Object的实例。
错误是发生在5008建议调用fusion接口后对数据进行
二次序列化时,且该部分代码本期迭代没有调整过,已经安然运行几个月。
排查方式
1,首先在开发机环境调试发现windows开发机运行完全正常。
2,远程调试测试发现mcpack返回的数据对象中List<Map>部分不正常,本应为String的对象被转化成了Object对象。
3,进而反编译Mcpack和json-rpc包进行调试,发现fusion返回的数据正常,而通过json-rpc解析后的对象就错了,但windows正常。且linux下jsonrpc执行的代码部分有遗漏
4,通过maven查询公司库中json-rpc包有2个主要分支,我们使用的在反序列化时使用的是jachson,而另外一个分支是使用的gson。
5,通过排查lib目录发现凤睛项目所带的json包中将jsonrpc另外分支中的代码加入,导致包覆盖的问题。问题被定位
异常原因及分析
1,java的classloader对class的识别是通过包名加类名识别的,而两个包中的包名使用相同,故导致后面的加载不到
2,因gson对泛型的反序列化存在bug,导致凤睛引入的jsonrpc包解析存在问题
3,windows与linux对文件排序方式不同,导致包加载顺序不同从而使得被首次加载的class不同
改进手段和建议
1,项目在引入json-rpc这种底层包时尽量通过maven引入,再进行扩展。如果一定需要重新封装,要修改包名
2,项目接入时要进行依赖排查,确保不对现有依赖造成覆盖
3,部门级别形成统一的底层包管理,使得这种底层的包依赖被管理起来