一文帶你解決Java項(xiàng)目開(kāi)發(fā)中java.lang.NoSuchMethodError的問(wèn)題
前言
在日常 Java 開(kāi)發(fā)中,大家應(yīng)該都見(jiàn)過(guò)這種報(bào)錯(cuò):
java.lang.NoSuchMethodError: '返回類型 包名.類名.方法名(參數(shù)列表)'
這個(gè)錯(cuò)誤看似“方法不存在”,但實(shí)際上大多數(shù)情況下方法明明寫在代碼里,IDE 編譯也能過(guò),就是運(yùn)行時(shí)突然報(bào)錯(cuò)。本文就帶大家拆解一下問(wèn)題的本質(zhì),結(jié)合實(shí)際案例演示如何排查和解決。
問(wèn)題背景:編譯和運(yùn)行時(shí)依賴不一致
NoSuchMethodError 并不是說(shuō)你拼寫錯(cuò)了方法,而是 運(yùn)行時(shí)環(huán)境加載的類和編譯時(shí)使用的類不一樣。
比如:
- 你在開(kāi)發(fā)時(shí)引入了 1.2 版本的依賴庫(kù),編譯時(shí)用到了其中新增的方法。
- 但實(shí)際運(yùn)行時(shí),項(xiàng)目里加載的是 1.0 版本的依賴庫(kù),那個(gè)方法還沒(méi)被實(shí)現(xiàn)。
- 結(jié)果:運(yùn)行時(shí)找不到方法,就報(bào)
NoSuchMethodError。
這個(gè)問(wèn)題在 Maven / Gradle 項(xiàng)目、Spring Boot 多模塊項(xiàng)目里特別常見(jiàn),因?yàn)橐蕾噦鬟f很容易導(dǎo)致版本沖突。
Demo 示例:重現(xiàn) NoSuchMethodError
我們先來(lái)寫個(gè)最小復(fù)現(xiàn)案例。
依賴庫(kù)(lib-demo v1.0)
// lib-demo v1.0
package com.example.lib;
public class HelloService {
public String sayHello(String name) {
return "Hello " + name;
}
}
新版本依賴庫(kù)(lib-demo v1.2)
// lib-demo v1.2
package com.example.lib;
public class HelloService {
public String sayHello(String name) {
return "Hello " + name;
}
// 新增方法
public String sayHi(String name) {
return "Hi " + name;
}
}
主程序
package com.example.app;
import com.example.lib.HelloService;
public class Main {
public static void main(String[] args) {
HelloService service = new HelloService();
System.out.println(service.sayHi("Tom")); // 調(diào)用新方法
}
}
如果你在 編譯時(shí)用的是 lib-demo 1.2,一切正常。
但是運(yùn)行時(shí)只要 classpath 里加載的是 lib-demo 1.0,就會(huì)報(bào)錯(cuò):
Exception in thread "main" java.lang.NoSuchMethodError: 'java.lang.String com.example.lib.HelloService.sayHi(java.lang.String)'
如何排查
遇到這個(gè)問(wèn)題,排查的思路一般分三步:
1. 檢查依賴樹(shù)
如果是 Maven 項(xiàng)目,可以用:
mvn dependency:tree
Gradle 項(xiàng)目可以用:
./gradlew dependencies
看看是不是有多個(gè)版本的 lib-demo 被引入了。
例如:
[INFO] +- com.example:lib-demo:jar:1.2:compile
[INFO] \- com.other:some-lib:jar:1.0:compile
\- com.example:lib-demo:jar:1.0:compile
很明顯,some-lib 又帶進(jìn)來(lái)了低版本的依賴。
2. 確認(rèn)最終運(yùn)行的 JAR 包版本
即使在 pom.xml 里寫的是 1.2,運(yùn)行時(shí)可能還是加載到 1.0。
可以在運(yùn)行時(shí)加一句:
System.out.println(HelloService.class.getProtectionDomain().getCodeSource().getLocation());
這樣你就能打印出 JVM 實(shí)際加載的 HelloService 來(lái)自哪個(gè) JAR 包。
3. 清理緩存,確保依賴一致
有時(shí)候 Maven 本地倉(cāng)庫(kù)里舊版本沒(méi)更新,或者打包工具沒(méi)清理干凈。
建議執(zhí)行:
mvn clean install -U
確保本地緩存和遠(yuǎn)端一致。
解決方案
針對(duì)這種問(wèn)題,常見(jiàn)的解決方式有幾種:
方案一:排除沖突依賴
在 pom.xml 里明確排除掉低版本依賴:
<dependency>
<groupId>com.other</groupId>
<artifactId>some-lib</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>com.example</groupId>
<artifactId>lib-demo</artifactId>
</exclusion>
</exclusions>
</dependency>
方案二:鎖定依賴版本
使用 Maven 的 <dependencyManagement> 或 Gradle 的 resolutionStrategy 來(lái)強(qiáng)制使用指定版本:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-demo</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</dependencyManagement>
Gradle:
configurations.all {
resolutionStrategy {
force 'com.example:lib-demo:1.2'
}
}
方案三:清理并重建
有時(shí)候光是本地緩存問(wèn)題,直接清理一下就能解決:
mvn dependency:purge-local-repository
或者直接刪掉 ~/.m2/repository 對(duì)應(yīng)目錄,重新構(gòu)建。
實(shí)際場(chǎng)景中的意義
我自己在做一個(gè) Spring Boot 多模塊項(xiàng)目的時(shí)候就遇到過(guò)類似的坑:
- A 模塊用的是某個(gè)庫(kù)的 2.x 版本;
- B 模塊因?yàn)橐蕾嚵艘粋€(gè)老庫(kù),又把 1.x 的版本帶進(jìn)來(lái)了;
- 結(jié)果上線之后,某個(gè) API 調(diào)用直接報(bào)
NoSuchMethodError,排查半天才發(fā)現(xiàn)是依賴沖突。
這種問(wèn)題的危險(xiǎn)在于:編譯沒(méi)問(wèn)題,運(yùn)行才炸,所以一定要養(yǎng)成上線前檢查依賴樹(shù)的習(xí)慣。
總結(jié)
java.lang.NoSuchMethodError 本質(zhì)上就是 編譯和運(yùn)行時(shí)依賴版本不一致。
解決思路:
- 查依賴樹(shù),看看是不是被拉了舊版本。
- 確認(rèn)運(yùn)行時(shí)加載的 JAR 包是不是正確。
- 必要時(shí)排除、鎖定依賴版本,并清理緩存。
這樣一套流程走下來(lái),大多數(shù)問(wèn)題都能定位并解決。
到此這篇關(guān)于一文帶你解決Java項(xiàng)目開(kāi)發(fā)中java.lang.NoSuchMethodError的問(wèn)題的文章就介紹到這了,更多相關(guān)java.lang.NoSuchMethodError問(wèn)題解決內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Maven包沖突導(dǎo)致NoSuchMethodError錯(cuò)誤的解決辦法
- 詳解Matisse與Glide--java.lang.NoSuchMethodError:com.bumptech.glide.RequestManager.load
- Java異常 Factory method''sqlSessionFactory''rew exception;ested exception is java.lang.NoSuchMethodError:
- 解決啟動(dòng)Azkaban報(bào)錯(cuò)問(wèn)題:java.lang.NoSuchMethodError: com.google.common.collect.ImmutableMap.toImmutableMap
- 解決 java.lang.NoSuchMethodError的錯(cuò)誤
相關(guān)文章
Java利用位運(yùn)算實(shí)現(xiàn)加減運(yùn)算詳解
這篇文章主要為大家介紹了如何使用位運(yùn)算來(lái)實(shí)現(xiàn)加減功能,也就是在整個(gè)運(yùn)算過(guò)程中不能出現(xiàn)加減符號(hào)。文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-12-12
java使用異或?qū)崿F(xiàn)變量互換和異或加密解密示例
這篇文章主要介紹了使用異或?qū)崿F(xiàn)變量互換和異或加密解密示例,需要的朋友可以參考下2014-02-02
Java實(shí)現(xiàn)字符串與基本數(shù)據(jù)類型轉(zhuǎn)換的全面指南
本文詳細(xì)介紹了Java中字符串與基本數(shù)據(jù)類型之間轉(zhuǎn)換的方法,包括將字符串轉(zhuǎn)換為基本數(shù)據(jù)類型,以及將基本數(shù)據(jù)類型轉(zhuǎn)換為字符串的各種技術(shù),有需要的小伙伴可以了解下2025-09-09
Java MD5消息摘要算法原理及實(shí)現(xiàn)代碼
這篇文章主要介紹了Java MD5消息摘要算法原理及實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
idea 打包maven項(xiàng)目忽略test文件的操作
這篇文章主要介紹了idea 打包maven項(xiàng)目忽略test文件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02
IDEA下Servlet可能出現(xiàn)404的一些情況
相信有很多小伙伴遇到報(bào)錯(cuò)都不知道怎么處理,今天特地整理了這篇文章,文中對(duì)IDEA下Servlet可能出現(xiàn)404的一些情況作了詳細(xì)的介紹,需要的朋友可以參考下2021-06-06

