最近生产环境发生一件报错事件:在一个第三方平台调用我们平台接口的时候,偶发性的报错,java.lang.NoSuchMethodError:org.apache.commons.io.IOUtils.readFully(Ljava/io/InputStream;[B)V..............
报错原因:
IOUtils类中没有readFully()方法,通过反编译工具查找这个class类对应的jar包发现,其中一个jar包的类中的确缺少这个方法,但是另外一套环境,包括本地代码环境运行时却没有发现这个问题。
这说明在编译期没有报错,运行时,报错,然后后面导致进程终止,程序异常,并且此异常并没有在Log4J的log日志中体现,一开始排查并没有找到这个报错,查看nohup后台日志发现这个错误。
运行时报错根本原因:
该应用直接或者间接依赖了同一个类的多个版本,或者是不同jar包中同名的类。导致其中一个类,比如A.class中的readFully()方法,在B.class类中不存在,编译期间是使用A.readFully();而运行时是B.readFully(),而B.class中缺少方法导致引用报错。
导致出现原因:
在环境部署的时候,因为是整个拷贝,遗留的历史jar包没有对应删除,导致加载的不同的jar包中存在相同的class类。由于 JVM 类加载器对于同一个类只会加载一次,最终加载的类实现受到 Jar 包依赖的路径、类声明的先后顺序或文件加载顺序等因素的影响,很可能出现不同机器加载的类实现不一致。
解决办法:
1、删除其中一个jar,发现重新编译后并没有报错,猜测可能是一个无效的jar包引用,或者因为升级,原jar包并未使用。重启后,运行发现好使了