记一个由于依赖管理糟糕踩的坑

651 阅读1分钟
public void someMethod(long uid){
    set.add(uid);
    po.setString(JSON.toJSONString(set));
}// 这段代码是web项目的,online会调用
  • 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\ett\*.jar 的时候的断点,通过线程的栈帧和栈帧中的数据,很明显证明我的推测一是正确的,为我的直觉感到欣慰!