线上代码不符合预期? 反编译查看一下吧

42 阅读2分钟

背景

本周上线发布了一个小功能,功能很小,就是增加了一个if判断,可以简单理解为下面的情况。

private static final String PREFIX = "xxx";

private boolean valid(String input) {
   // 原有逻辑不变
   if (input.startsWith("xxx")) {
      return false;
   }
   return true;
}

这段代码相当简单,但是线上运行时,偶尔会发现返回不符合预期。

排查

阶段1:抓取线上日志,根据日志获取到对应的实际数据,通过main函数方式运行,发现运行结果符合预期,代码本身没有问题。

阶段2:分析日志,着重分析不符合预期发生的时间,该代码位于一个定时schedule job中,任务每2分钟执行一次,但是发生问题的时间点并非所有时间点,应用部署在4台机器上,怀疑和某台机器有关系。

阶段3:查看当天上线操作流程,应用原有3台机器,当天正常部署发布了最新代码。部署以后,为提升应用处理性能,做了一个机器扩容,增加到4台机器,所以当天增加的这台机器极大可能就是问题所在,怀疑有可能代码不是最新的。

阶段4:验证猜测。

step1. 登录机器,获取到部署的jar包,解压后获取到对应的class文件。 对于jar包的解压,可以直接运行以下命令。

unzip xxx.jar

step2.查看反编译class文件。

如果可以下载文件到本地,那么可以利用图形化的工具jad-gui方式,或者直接拖入intellij IDEA。

如果在linux机器上,可以借助jad命令,该程序需要安装,具体安装方式参照blog.csdn.net/irencewh/ar…

当然,还有java自带的命令javap,也可以用于反编译,并且jdk自身就已经携带,非常方便。关于javap命令参考: www.jianshu.com/p/6a8997560…

docs.oracle.com/javase/7/do…

通过示例代码,可以运行下面的命令,查看当前class文件中是否有对应的private static final String PREFIX变量声明。

javap -private xxx.class

阶段5: 重新部署解决,怀疑该问题还是由于部署和扩容同时进行,可能导致扩容的时候还是部署的旧代码导致的。

思考

针对该问题的发生,开始怀疑是自身代码出现问题,通过反复验证发现代码运行正常,不过也缺少了一些关键日志,用于自证清白。 同时对于该问题,最终找中间件的同学确认了一下,是由于做了一些构建加速,直接使用了旧包部署。该配置在大多数情况下没有问题,但是对于中间件也要持有一定的怀疑态度。