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

  最近接手新項目,項目一跑,NoSuchMethodError蹦出來了,好不容易解決了,換一個電腦,NoSuchMethodError又蹦出來了,乾脆,總結下遇到NoSuchMethodError應該如何應對的思路。java

  經過下面的通用思路,能夠在沒必要了解業務的狀況下,儘量解決這個報錯。web

  下面演示下如何在啥都不知道的狀況下遇到該錯誤的解決思路:spring

  隨便找一個錯誤示例服務器

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服務器時報的錯。一開始看時看到報錯,心裏是奔潰的,剛接手項目,之前代碼又不是我寫的,我怎麼知道會報找不到方法的是什麼緣由引發的啊。別急,先看引發這個錯誤有可能的緣由是什麼。框架

  錯誤可能的緣由eclipse

  1. 有這個類,該類真的沒有這個方法
  2. 有這個類,並且有好幾個,他們之間發生了衝突

  緣由排除maven

  1、點擊進入報錯的代碼所在行,在報錯的地方打一個debug點,重行啓動項目或重現該錯誤,讓程序運行到該行代碼:spa

     

    

  2、打開display界面(若沒有,請在window--show view裏面找出該界面),.net

  手動敲出xxx.class.getProtectionDomain().getCodeSource(),xxx爲報錯的類的全類名,鼠標選中該行代碼,點擊界面右上角的J圖標,即會打印出到該類對應的包所在的地址。以下圖所示。  debug

  能夠看到,結果爲:

  (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這個包試試。

  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包衝突,緣由有兩個:

  一、 本項目A自己引用了ecj-3.5.1.jar包,同時引入了項目B,而項目B引入了core-3.1.1.jar,因此本項目也至關於引入了core-3.1.1.jar,這就是maven項目中常見的jar包衝突。

  二、 那爲何maven沒有自動幫咱們解決jar包衝突呢,那是由於ecj-3.5.1.jar包和core-3.1.1.jar包的groupIdartifactId都不同,因此maven認爲這是兩個jar包,並不衝突,解決的辦法就是像上面那樣,加入exclusions排除。因此咱們在開發一個組件的時候,起名字是一個很重要的問題,若是升級組件連名字也改了,用戶會產生很大的不方便。

  再次啓動項目,問題解決。

相關文章
相關標籤/搜索