java--遇到NoSuchMethodError通用解决思路

出处:  http://www.cnblogs.com/xiaoMzjm/p/4566672.html


最近接手新项目,项目一跑,NoSuchMethodError蹦出来了,好不容易解决了,换一个电脑,NoSuchMethodError又蹦出来了,干脆,总结下遇到NoSuchMethodError应该如何应对的思路。

通过下面的通用思路,可以在不必了解业务的情况下,尽可能解决这个报错。

下面演示下如何在啥都不知道的情况下遇到该错误的解决思路:

随便找一个错误示例:
Caused by: java.lang.NoSuchMethodError: org.eclipse.jdt.internal.compiler.Compiler.<init>(Lorg/eclipse/jdt/internal/compiler/env/INameEnvironment;Lorg/eclipse/jdt/internal/compiler/IErrorHandlingPolicy;Lorg/eclipse/jdt/internal/compiler/impl/CompilerOptions;Lorg/eclipse/jdt/internal/compiler/ICompilerRequestor;Lorg/eclipse/jdt/internal/compiler/IProblemFactory;)V
    at com.taobao.sketch.compile.Compiler.generateClass(Compiler.java:392)
    at com.taobao.sketch.compile.Compiler.compile(Compiler.java:38)
    at com.taobao.sketch.compile.SketchCompilationContext.globalVmCompile(SketchCompilationContext.java:403)
    at com.taobao.sketch.runtime.SketchRuntimeServer.getGlobalVmTemplate(SketchRuntimeServer.java:622)
    at com.taobao.sketch.runtime.SketchRuntimeServer.resolveGloabalVm(SketchRuntimeServer.java:136)
    at com.taobao.sketch.runtime.SketchRuntimeServer.initializeVmLibrary(SketchRuntimeServer.java:127)
    at com.taobao.sketch.runtime.SketchRuntimeServer.init(SketchRuntimeServer.java:96)
    at com.taobao.sketch.SketchEngine.init(SketchEngine.java:66)
    at com.taobao.sketch.service.impl.SketchEngineImpl.init(SketchEngineImpl.java:118)
    at com.alibaba.citrus.springext.support.BeanSupport.afterPropertiesSet(BeanSupport.java:80)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335)
    ... 39 more

这是一个webx框架下的javaweb项目,在启动jetty服务器时报的错。一开始看时看到报错,内心是奔溃的,刚接手项目,以前代码又不是我写的,我怎么知道会报找不到方法的是什么原因引起的啊。别急,先看引起这个错误有可能的原因是什么。

错误可能的原因:
  1. 有这个类,该类真的没有这个方法
  2. 有这个类,而且有好几个,他们之间发生了冲突
原因排除:

1、点击进入报错的代码所在行,在报错的地方打一个 debug 点,重行启动项目或重现该错误,让程序运行到该行代码:

2、打开 display 界面(若没有,请在window--show view里面找出该界面),

手动敲出 xxx.class.getProtectionDomain().getCodeSource() ,xxx为报错的类的全类名,鼠标选中该行代码,点击界面右上角的J图标,即会打印出 到该类对应的包所在的地址。如下图所示。

可以看到,结果为:

(java.security.CodeSource) (file:/D:/Program%20Files%20(x86)/eclipse/configuration/org.eclipse.osgi/843/0/.cp/lib/core-3.1.1.jar <no signer certificates>)

3、接着复制该类的全类名,快捷键 Ctrl+Shift+T 打开 open type 界面,查看我们的项目引用到的包中,哪些有这个类:

我们发现有两个包中有org.eclipse.jdt.internal.compiler.Compiler这个类,分别为:

包一:ecj.3.5.1.jar

包二: core-3.1.1.jar

地址分别为:

但我们发现,刚刚在 display 中,我们看到的地址,居然不是来自这上面两个地址(上面两个包的地址都在 C 盘, DEBUG 中的包来自 D 盘),也就是说,实现运行环境引入的包,并不是在我们自己项目中配置的,因为 open typy 只能找到自己项目中配的东西。

那么 D 盘的这个包,在什么地方引入的呢?

想想,这个错误是在项目启动时报的,那么除了项目,还有“服务器”可能会引入其他包,那么有没有可能是服务器帮我们引入呢?

4 、打开服务器的 Classpath ,可以找到服务器确实引入了这个包

那么我们在服务器的 classpath 中把这个包“ remove ”掉。

5 、再次重新启动项目, dubug 、卡点、 display ,这次结果如下:

发现:实际环境中,现在己经没有引入 D 盘那个 core-3.1.1.jar 包了。我们让项目运行下去,发现还是报同样的错——找不到方法。那么接下来我们让项目引用 ecj.3.5.1.jar 这个包试试。

6 、 ctrl+shift+T 、双击进入 core-3.1.1.jar 中 Compiler 类所在的目录结构:

提示:左边栏勾上这个标志,即可展开该包所在的目录:

同理,打开 ecj.3.5.1.jar 中 Compiler 类所在的目录结构。

最后发现,这个 jar 包都同一个项目下面,而且两个包都有 Compiler类,且排在前面的是 core-3.1.1.jar ,但是 core-3.1.1.jar 的 Compiler 类并没有我们想要的方法, 所以报错 了 。但是 eclipse 在找类的时候,只要按顺序找到一个,就不会往下找了,所以排在下面的 ecj-3.5.1.jar 并不会被找到,即使里面有 Compiler 这个类,且有我们想要的方法。

7 、排除 core-3.1.1.jar 包:

该项目是maven项目。我们尝试直接在该项目的 pom.xml 中搜索 core 这个包是搜索不到的,那么这个 core-3.1.1 包可能是因为本项目引入其他项目,而其他项目引入 core-3.1.1.jar ,所以本项目间接把该包引过来了。

同时,因为该项目是 maven 项目,可以通过以下该方法排除这个包:

排除后,该项目的 pom.xml 变成:

假如是 非maven 项目,那么可以直接从lib中除去该包,或从项目根目录下面打开.classpath文件,找到对应的包的配置,删除该行即可。

通过该 pom.xml 我们可以知道,之所以会产生 jar 包冲突,原因有两个:

1、 本项目 A 本身引用了 ecj-3.5.1.jar 包,同时引入了项目 B ,而项目 B 引入了 core-3.1.1.jar,所以本项目也相当于引入了 core-3.1.1.jar ,这就是 maven 项目中常见的 jar 包冲突。

2、 那为什么 maven 没有自动帮我们解决 jar 包冲突呢,那是因为 ecj-3.5.1.jar 包和 core-3.1.1.jar 包的 groupId 和 artifactId 都不一样,所以 maven 认为这是两个 jar 包,并不冲突,解决的办法就是像上面那样,加入 exclusions 排除。 所以我们在开发一个组件的时候,起名字是一个很重要的问题,如果升级组件连名字也改了,用户会产生很大的不方便。

再次启动项目,问题解决。


  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值