项目中,经常会遇到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
org.apache.poi
poi
3.2-FINAL
commons-beanutils
commons-beanutils
1.7.0
输出结果:
[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即可。