对于maven项目经常会出现,项目引入一堆依赖,最后项目运行的时候出现
NoSuchMethod
ClassNotFound
NoClassDefFound
这些exception,这个时候就要怀疑是不是引包的姿势不对,导致了项目启动出现问题!
Root Cause:
一般出现以上exception的根本原因是,a,b不同的依赖之间依赖了同一个依赖c的不同版本,在A版本中某个类还在,但是在B版本中对应的类已经被删除了,maven依赖的时候根据自身的规则依赖了B版本,导致了应用在调用a的方法时,出现了NoSuchMethodException
ps:这里稍微提一下maven的依赖加载机制,我们都知道classloader是根据全路径名去加载一个类的,所以maven在依赖jar包时不可能对同一个jar包依赖多次,maven在加载jar时会根据加载的依赖复杂度去决定加载哪一个版本依赖,例如应用-->A-->B-->C(1.0.2), 应用-->D-->C(1.0.1),maven在向项目导入依赖的时候只会导入C(1.0.1),因为其依赖的复杂度(层数)比较低;那如果出现复杂度一样的情况,maven又是怎么做的呢,maven会根据pom文件中的顺序导入依赖,比较靠前的先导入
下面我们来人工模拟下NoSuchMethodException的出现情况:
首先是底层依赖的包,对应root cause中提到的c
/**
* Created by Roy on 16/9/11.
*/
public class DependencyBeanB {
public void dependMethodA(){
System.out.println("You depend on method A");
}
// public void dependMehtodB(){
// System.out.println("You depend on method B");
// }
}
maven install 到本地仓库 版本是1.0.1
/**
* Created by Roy on 16/9/11.
*/
public class DependencyBeanB {
// public void dependMethodA(){
// System.out.println("You depend on method A");
// }
public void dependMehtodB(){
System.out.println("You depend on method B");
}
}
maven install 到本地仓库 版本是1.0.2
二层依赖,对应root cause中提到的a
/**
* Created by Roy on 16/9/11.
*/
public class SecondInvokerA {
public void invoke(){
DependencyBean dependencyBean = new DependencyBean();
dependencyBean.dependMethodA();
}
}
<dependencies>
<dependency>
<groupId>com.roy</groupId>
<artifactId>maven-test-jar</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
对应root cause 中提到的b
/**
* Created by Roy on 16/9/11.
*/
public class SecondInvokerB{
public void invoke(){
DependencyBean dependencyBean = new DependencyBean();
dependencyBean.dependMehtodB();
}
}
<dependencies>
<dependency>
<groupId>com.roy</groupId>
<artifactId>maven-test-jar</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
应用
public class DependencyInvoker {
public static void main(String[] args) {
System.out.println("Invoker main method invoke.");
SecondInvokerB secondInvoker = new SecondInvokerB();
secondInvoker.invoke();
}
}
<dependencies>
<dependency>
<groupId>com.roy</groupId>
<artifactId>depend-project-a</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.roy</groupId>
<artifactId>depend-project-b</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
运行应用 错误出现:
Invoker main method invoke.
Exception in thread "main" java.lang.NoSuchMethodError: com.roy.test.DependencyBean.dependMehtodB()V
at com.roy.SecondInvokerB.invoke(SecondInvokerB.java:12)
at com.roy.DependencyInvoker.main(DependencyInvoker.java:11)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
知道了是由于重复依赖导致了问题,我们就要解决问题了
两种方式,
一,通过http://maven.apache.org/plugins/maven-dependency-plugin/ 插件在项目未运行前就发现问题,防患于未然
二,如果没有依赖这个插件,问题发生了怎么办,方法一,可以借助IDE的依赖图找到重复依赖,然后exclude掉(实际项目中出现方法,类找不到一般都是传递依赖了版本较低的包,跟以上举的例子不太一样),方法二,通过mvn dependency:tree -Dverbose 命令直接找到被忽略依赖的包,然后exclude掉出现问题jar(一般都是引入低版本包出的问题,因为高版本的包一般都会做向下兼容)
[INFO] Building maven-classload 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ maven-classload ---
[INFO] com.roy:maven-classload:jar:1.0-SNAPSHOT
[INFO] +- com.roy:depend-project-a:jar:1.0-SNAPSHOT:compile
[INFO] | \- com.roy:maven-test-jar:jar:1.0.1:compile
[INFO] \- com.roy:depend-project-b:jar:1.0-SNAPSHOT:compile
[INFO] \- (
com.roy:maven-test-jar:jar:1.0.2:compile - omitted for conflict with 1.0.1)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.782 s
[INFO] Finished at: 2016-09-11T22:27:21+08:00
[INFO] Final Memory: 11M/155M
[INFO] ------------------------------------------------------------------------
红色部分指出,当前依赖的jar被另一个版本的取代了,这个时候你就要根据实际情况exclude掉一个
分享到:
相关推荐
eclipse导入maven项目报错解决办法,找了好多网上的都零零碎碎的,希望以后遇到会有所帮助.
下面小编就为大家分享一篇解决maven启动Spring项目报错的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
Maven是基于项目对象模型,可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。如今用到Maven的地方很多,而在用Eclipse开发项目时经常导入Maven项目时出现此类错误,在这里记录下来解决办法。
今日,将原先在eclipse上开发的Maven项目导入idea中,启动报错,项目在eclipse中启动百分百是没有问题,误以为是IDEA打开项目的动作错误,在网上查了很多资料,各种操作五花八门,尝试了遍,结果还是不行。...
不习惯于maven项目开发,想使用eclipse的普通web项目。想借鉴别人的maven项目,但是自己使用的却不熟悉maven的原理等等,但是需要懂一点maven的目录架构。
NULL 博文链接:https://yansxjl.iteye.com/blog/2352594
主要介绍了关于maven打包时的报错: Return code is: 501 , ReasonPhrase:HTTPS Required,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
Eclipse新建和部署maven项目,每一步都有详细的截图
主要介绍了Java MAVEN 工程pom配置报错解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
在平时工作中的maven开发遇到的报错问题
使用Maven整合Kafka 包括生产者,消费者 Kafka各种配置 //1.设置参数 Properties props = new Properties(); props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "81.68.232.188:9092,81.68.232.188:9093,81...
基于elasticjob的入门maven项目 基于elasticjob的入门maven项目 基于elasticjob的入门maven项目 基于elasticjob的入门maven项目 基于elasticjob的入门maven项目 基于elasticjob的入门maven项目 基于elasticjob的入门...
IDEA中Maven依赖包报错的问题解决方案汇总.docx
<groupId>net.sf.json-lib</groupId> <artifactId>json-lib <version>2.4 <classifier>jdk15 或者直接下载这个包
java创建一个简单的Maven项目java创建一个简单的Maven项目java创建一个简单的Maven项目java创建一个简单的Maven项目java创建一个简单的Maven项目java创建一个简单的Maven项目java创建一个简单的Maven项目java创建一...
maven项目构建文档maven项目构建文档maven项目构建文档
maven项目eclipse导入的详细步骤。
基于Springboot+mybatis的maven项目
失败报错如下: Failed to execute goal org.apache.maven.plugins:maven-help-plugin:3.1.0:system (default-cli) on project standalone-pom: Execution default-cli of goal org.apache.maven.plugins:...
sypro_maven项目,ssh_maven项目