最近由于项目的脚手架升级,导致项目中的各个jar包中间产生了很大的冲突,从而启动不起来。
参考了网上的一些方法,分享下走过的坑,若有什么不对的地方,或者疑问的地方,欢迎指出或者一起探讨下啦~

NoSuchMethodError和classNotFoundException
两个问题的解决方法是一样的呢,一个是方法找不到,一个是类不到,我先大概我理解的怎么产生的原因,和解决的版本,如果有什么讲的不对的地方,欢迎指出呀~

先看看问题

NoSuchMethodError 或 classNotFoundException 发生原因和解决办法

运行时抛出 的原因是什么?

当应用程序试图调用类(静态或实例)的指定方法,而该类已不再具有该方法的定义时,就会抛出
java.lang.NoSuchMethodError 错误。简单地说,就是同一个 Class
有多个版本的实现,并且在运行时调用了缺少方法的那个版本。(缺失jar包或是jar冲突)

NoSuchMethodError 或 classNotFoundException 发生原因和解决办法
简单通俗的来讲,就是在项目启动的时候,有两个版本 1.0.0 和1.1.0 ,他们的类名一样 但里面的方法不一致 那么 JVM 类加载器对于同一个类名只会加载一次。这样可能我们需要1.0.0的版本 而他给我们加载了1.1.0的版本 那样就会报错 所以可能就会出现图上那种情况


这样会有个疑问 ,jvm是加载1.0.0或是1.1.0由什么决定的呢?
maven有个依赖仲裁机制
1 版本声明——》 2 是加载路径最短的 ——》3 加载优先调用的

jvm 的也有个加载顺序 — 双亲委派机制

NoSuchMethodError 或 classNotFoundException 发生原因和解决办法

首先,Maven 依赖仲裁机制 决定了打包的优先级, 仲裁优先级“从高到低”如下所述:

  • 优先按照依赖管理 [dependencyManagement] 元素中指定的版本进行仲裁;

  • 若无版本声明,则按照 “短路径优先” 原则(Maven2.0)进行仲裁,即选择依赖树中路径最短的版本;

  • 若路径长度一致,则按照 “第一声明优先” 原则进行仲裁,即选择 POM 中最先声明的版本。

注:合理使用 Maven 依赖仲裁机制可以便捷的管理 Jar 包版本而不合理的使用将导致多版本 Jar 冲突。

其次,JVM 类加载机制 决定了 Class 被加载到 JVM 的优先级, 如果同一个类出现在多个 Jar 包中,那么在 双亲委派类加载机制
下,加载该 Jar 包的类加载器层级越高,该 Jar 包越先被加载,它所包含的 Class 越先被执行,如上图所示:

  • 启动类加载器(Bootstrap ClassLoader) 优先级最高,主要加载 JVM 运行时核心类,如 java.*等,这些类位于 $JAVA_HOME/lib/rt.jar 文件中
  • 扩展类加载器(Extention ClassLoader) 优先级次之,主要加载 JVM 扩展类,如 swing 组件、xml 解析器等,这些类主要位于 $JAVA_HOME/lib/ext/ 目录下的 Jar 包中。
  • 应用类加载器(Application ClassLoader) 又称系统类加载器,优先级再次之,它会加载 Classpath环境变量里定义的路径中的 Jar 包和目录,通常我们自己编写的代码或依赖的第三方 Jar 包都是由它来加载。

除了上述两种原因外,在同一个 ClassLoader 下,如果存在一个 Class 出现在不同的 Jar 包中,那么文件系统的文件加载顺序也可能会影响最终的加载结果。因此,应该尽量保证开发/测试/生产系统环境一致性。


那么如何解决?

下面是我这次解决版本冲突的方法步骤

1. 首先先确定下,看下控制台,缺少了那些类或者方法
NoSuchMethodError 或 classNotFoundException 发生原因和解决办法

  1. 通过网址(https://findjar.com/)确定是哪个jar包(如果知道那个jar包直接跳过 步骤 2 )
    NoSuchMethodError 或 classNotFoundException 发生原因和解决办法
    NoSuchMethodError 或 classNotFoundException 发生原因和解决办法

  2. 在通过idea中的maven依赖 show Dependencies 来查询jar版本是否异常,是否存在如果缺失 补上,存在就选择需要的版本,排除不需要的版本

NoSuchMethodError 或 classNotFoundException 发生原因和解决办法
NoSuchMethodError 或 classNotFoundException 发生原因和解决办法

NoSuchMethodError 或 classNotFoundException 发生原因和解决办法
一般由红线就是版本冲突


其他办法可以借鉴下,综合使用

或者看这个external libaraies查看是否由jar导入了多个版本 在排除(比较慢)

NoSuchMethodError 或 classNotFoundException 发生原因和解决办法

或者在打开项目的pom.xml文件中,可以直接查看冲突,和项目中使用的版本

NoSuchMethodError 或 classNotFoundException 发生原因和解决办法


本文介绍的 Jar 包冲突解决方法,除了解决 本文中的两个异常 以外,对其他相似问题也具备一定的参考价值

例如 java.lang.ClassNotFoundException,即加载不到指定类,通常是 Maven仲裁选错了版本
如本地开发阶段调用了 1.2.0 版本,而打包时采用了 1.0.0 版本的 Jar 包。同理,java.lang.NoClassDefFoundError 和 java.lang.LinkageError 也可以基于上述思路进行排查。 此外,如果类和方法名都保持不变,但是内部实现有变化,在多版本冲突场景下,不会抛出异常,但程序行为跟预期不一致, 此时,也可以基于上述思路进行排查诊断。

相关文章: