問題現象
近期本人負責的一個SpringBoot模塊出現了java.lang.NoSuchMethodError
報錯,問題情況如下:
- A類提供了
setJumpType(String type)
,B類調用A類的setJumpType(String type)報錯java.lang.NoSuchMethodError: com.xxx.A.setJumpType(Ljava/lang/String;)V
- 在之前的發版的程序中,B類無變更,出現以上問題後,重新編譯B類問題解決。
常見該問題原因與解決方法
- 方法不存在:變更實現
- 方法簽名變更(一般博客中只關注到方法名與參數列表):修正方法名與參數列表
問題分析
- 反編譯代碼和本地IDE源碼調試均無該報錯出現,方法是存在的
- 檢查A類是否存在方法名稱和參數類型、數量變更,發現也沒問題
- 使用
javap -v
命令分析,經比較之前編譯的與新編譯的B類調用A類的方法簽名中,返回值不同
處理方法
- 原因確定是方法簽名的返回值發生變更
- 既然這個類是個DTO對象,就可以不直接用對方的DTO,重寫一份放自己這邊解決該問題,類似的情況只能靠發版前,在測試環境自測功能是否正常,有問題及時發現與解決
問題總結
java.lang.NoSuchMethodError
錯誤出現於方法不存在和簽名變更的情況- 方法簽名格式:
類路徑.方法名(參數列表;)返回值類型
- 返回值類型:void->V; 引用->L類路徑;
- 方法簽名中除了類路徑變更會導致ClassNotFound異常外,(方法名、參數列表、返回值類型)發生變化都會引起NoSuchMethodError錯誤,可根據錯誤原因進行處理
- 編譯的class文件中不僅包含自身源文件的編譯結果,還包含引用的類與方法的簽名信息,一旦簽名發生變更就會出現兼容性問題,可能造成NoSuchMethodError錯誤。