事出有因
// 这段代码是 web 项目的 online 会调用
public void someMethod(long uid){
set.add(uid);
po.setString(JSON.toJSONString(set));
}
someMethod(long)
很简单,就是将存储 uid 的Set<Long>
通过 fastjson 转成String
咋一看没什么问题,但是在反序列化的时候,uid 会默认为Integer
这个时候就有类型强转问题了。所以需要改成JSON.toJSONString(set, SerializerFeature.WriteClassName)
附加类型名。这样的String
就是Set[1234567890L]
那么反序列化也OK了
问题排查
-
改完之后本地确实没有问题,上线后 web 项目也没问题,但是 online 项目在反序列化的时候就报错了
com.alibaba.fastjson.JSONException: exepct '[', but error
查了半天,最后怀疑线上 online 的jar
包有问题,联系运维查了下 online 的classpath
,不出所料,当时内心十分日狗 -
这里又关系到
class
的加载问题,但是很明显 online 用的是 1.1.2 的版本,推测原因有二:- 其一
File#compareTo(File pathname)
最后调用的还是String#CaseInsensitiveComparator#compare(String, String)
- 其二由于该排序是
linux
默认的,所以classloader
加载的时候会判断,如果已经加载过同包同类的class
,则不加载后者
- 其一
总结一下
其实这个问题就是依赖管理糟糕的坑,至于为什么线上 online 会有两个 fastjson ,我也问了运维,历史原因。但是,如果是用maven
管理依赖,应该会避免此类问题
后续
还是想搞清楚到底怎么回事!
下面两个图是在加载 jre\lib\ext\*.jar
的时候的断点,通过线程的栈帧和栈帧中的数据,足以说明我的推测一是正确的,为我的直觉感到欣慰!