项目中,经常会遇到ClassNotFound,NoSuchMethod异常,第一反应往往是类路径不对,jar没有正确的引用。第一步判断jar是否加载,还是 加载的jar由于maven依赖管理存在传递依赖,造成依赖的jar版本号不对,相应的类找不到,或者是相应类版本不对,没有对应的方法。
一 造成jar 冲突的原因:如果项目中存在对同一jar不同版本依赖的时候,maven 2根据最近原则,默认引用最靠近项目版本的jar,maven 2.0.9会根据最先声明原则 来引用相应版本的jar;无论那种方式,都会出现jar包冲突。在这里提一下gradle依赖,会依赖最新版本的jar。
二 判断jar是否正确的被引用 有两种方法:
1在项目启动时加上VM参数:-verbose:class
项目启动的时候会把所有加载的jar都打印出来 类似如下的信息:
classpath加载的jar
-
-classpath /home/yao/tool/jdk1 .8 .0_25/jre/lib/jce.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/resources.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/rt.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/management-agent.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/jfxswt.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/plugin.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/javaws.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/charsets.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/jsse.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/deploy.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/jfr.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/ext/localedata.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/ext/nashorn.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/ext/jfxrt.jar:
-
/home/yao/tool/jdk1 .8 .0_25/jre/lib/ext/sunjce_provider.jar:
-
...............等等
具体load的类
[Loaded java.lang.Object from /home/yao/tool/jdk1.8.0_25/jre/lib/rt.jar]
[Loaded java.io.Serializable from /home/yao/tool/jdk1.8.0_25/jre/lib/rt.jar]
[Loaded java.lang.Comparable from /home/yao/tool/jdk1.8.0_25/jre/lib/rt.jar]
[Loaded java.lang.CharSequence from /home/yao/tool/jdk1.8.0_25/jre/lib/rt.jar]
[Loaded java.lang.String from /home/yao/tool/jdk1.8.0_25/jre/lib/rt.jar]
[Loaded java.lang.reflect.AnnotatedElement from /home/yao/tool/jdk1.8.0_25/jre/lib/rt.jar]
[Loaded java.lang.reflect.GenericDeclaration from /home/yao/tool/jdk1.8.0_25/jre/lib/rt.jar]
[Loaded java.lang.reflect.Type from /home/yao/tool/jdk1.8.0_25/jre/lib/rt.jar]
[Loaded java.lang.Class from /home/yao/tool/jdk1.8.0_25/jre/lib/rt.jar]
..................等等
我们可以通过上面的信息查找对应的jar是否正确的被依赖,具体类加载情况,同时可以看到版本号,确定是否由于依赖冲突造成的jar引用不正确;
2 通过maven自带的工具:mvn dependency:tree
具体后面可以加 -Dverbose 参数 ,详细参数可以去自己搜,这里不详细介绍。
比如分析如下POM
运行: mvn dependency:tree -Dverbose
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.2-FINAL</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.7.0</version>
</dependency>
</dependencies>
输出结果:
-
[ INFO] ------------------------------------------------------------------------
-
[ INFO]
-
[ INFO] --- maven-dependency- plugin: 2.8 :tree (default-cli) @ Dependency ---
-
[ INFO] com. yao: Dependency :pom : 1.0- SNAPSHOT
-
[ INFO] +- org.apache. poi: poi: jar: 3.2- FINAL :compile
-
[ INFO] | +- commons- logging: commons- logging: jar: 1.1 :compile
-
[ INFO ] | | \- log4j: log4j: jar: 1.2 . 13 :compile
-
[ INFO ] | \- ( log4j: log4j: jar: 1.2. 13 :compile - scope updated from runtime; omitted for duplicate)
-
[ INFO] \- commons- beanutils:commons- beanutils: jar: 1.7. 0 :compile
-
[ INFO] \- (commons- logging:commons- logging: jar: 1.0. 3 :compile - omitted for conflict with 1.1)
-
[ INFO] ------------------------------------------------------------------------
通过里面的信息可以看到 两个jar都commons-logging存在依赖,但是版本不同。里面的详细信息显示引用了 commons-logging:commons-logging:jar:1.1 去掉了commons-logging:commons-logging:jar:1.0.3 (omitted for duplicate)。
通过以上方法我们可以看到项目中引用jar版本号;接下来就是如何排除掉我们不想要版本的jar;
三 通过Idea intellij 中的Show Dependencies的工具去除重复的jar
在Pom.xml文件上右击 选择 Diagrams -> Show Dependencies 即可查看Pom的依赖图,通过图可以很容易的看到依赖冲突的jar,exculude掉不想要的版本jar即可。