接入一个插件或第三方 SDK 后出现类冲突和 NoSuchMethodError,你会怎么从类加载器角度排查?
我的判断
NoSuchMethodError 基本意味着编译时和运行时看到的类版本不同,先找“这个类到底从哪个 jar、哪个加载器来”,再谈排包。
我会拿异常里的类名和方法描述符,先用依赖树确认编译版本,再在运行实例执行类加载日志或查看 protection domain,找到实际 jar。插件系统还要看宿主和插件各自的 ClassLoader;同名类由不同加载器加载,在 JVM 看来就是不同类型。
-Xlog:class+load=info
jcmd <pid> VM.classloaders
javap -classpath suspect.jar -p package.ClassName
短期修复是统一版本、排除传递依赖,或对第三方冲突包做 shading。长期会给插件定义稳定 SPI,让共享接口由父加载器加载,插件私有依赖走隔离加载器,避免把宿主内部类暴露成协议。
我不会靠反复调整 jar 顺序碰运气;那只会让当前环境加载到“刚好能跑”的版本,下次构建顺序变化还会复发。
思路拆解问题分析
NoSuchMethodError 发生在链接或调用阶段:类本身找到了,但运行时版本没有调用方字节码要求的方法。它和业务代码抛出的异常不同,try/catch 重试通常没有意义。