实际开发中遇到java.lang.NoSuchMethodError

在开发中遇到java.lang.NoSuchMethodError的错误。

java.lang.NoSuchMethodError: 
com.sinosoft.ims.api.kernel.dto.RequestPrpDuserDto.getCodeMethod()Ljava/lang/String;     
at com.sinosoft.ims.core.kernel.service.impl.PrpDuserServiceImpl.queryHandler1CodeInfo(PrpDuserServiceImpl.java:127)     
at com.sinosoft.ims.core.kernel.service.impl.PrpDuserServiceImpl$$FastClassBySpringCGLIB$$5429f8a0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)     
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)     
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)     
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52)

看到这个错误,首先想到有没有这个方法,要是没有就加上。但是代码中是存在的,重新编译运行还是报同样的错误。

错误可能的原因

  1. 有这个类,该类真的没有这个方法
  2. 有这个类,但是改方法出现问题,也是会出现这个bug
  3. 有这个类,而且有好几个,他们之间发生了冲突

在博客中看到一篇解决办法,还是不错的。下面是我的具体的解决方法:

原因排除

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



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>)

PS:若是其他错误也会在此提示出来。

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这个包试试。

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

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



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

  最后发现,这个jar包都同一个项目下面,而且两个包都有Compiler类,且排在前面的是core-3.1.1.jar,但是core-3.1.1.jarCompiler类并没有我们想要的方法,所以报错。但是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包的groupIdartifactId都不一样,所以maven认为这是两个jar包,并不冲突,解决的办法就是像上面那样,加入exclusions排除。所以我们在开发一个组件的时候,起名字是一个很重要的问题,如果升级组件连名字也改了,用户会产生很大的不方便。

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


ps:我的项目出现此问题原因是提示报错行那个方法不能转换成json,加上了注解,执行第1步和第2步即找到具体报错原因。




猜你喜欢

转载自blog.csdn.net/qq_30546099/article/details/80966745