NoSuchMethodError、LinkageError、行為詭異
Bootstrap Class Loader (JAVA_HOME/jre/lib/rt.jar)
↑ 委派
Extension Class Loader (JAVA_HOME/jre/lib/ext/*.jar)
↑ 委派
System / Application Class Loader (CLASSPATH / -cp)
↑ 委派
Custom Class Loaders (Web 容器、OSGi、熱部署等)
載入順序:父優先委派 → 自己找。System Class Loader 依 Classpath 項目順序 線性掃描,第一個匹配即載入,後續忽略。
which 啟發which java 顯示 PATH 中第一個 java 可執行檔路徑。Java 需要同樣工具:給定類別名,輸出實際載入的 .class 檔絕對路徑 (含 JAR 內路徑)。
> java JWhich com.clarkware.ejb.ShoppingCartBean
Class 'com.clarkware.ejb.ShoppingCartBean' found in
'/home/mclark/classes/com/clarkware/ejb/ShoppingCartBean.class'
> java JWhich javax.servlet.http.HttpServlet
Class 'javax.servlet.http.HttpServlet' found in
'file:/home/mclark/lib/servlet.jar!/javax/servlet/http/HttpServlet.class'
public class JWhich {
public static void main(String[] args) throws Exception {
String className = args[0];
// 關鍵:直接詢問系統類別載入器
ClassLoader cl = ClassLoader.getSystemClassLoader();
// 或 Thread.currentThread().getContextClassLoader()
String resourcePath = className.replace('.', '/') + ".class";
URL url = cl.getResource(resourcePath);
if (url == null) {
System.out.println("Class not found in classpath");
} else {
System.out.println("Class '" + className + "' found in");
System.out.println("'" + url + "'");
}
}
}
關鍵 API: ClassLoader.getResource(String name) — 依載入器搜尋順序返回第一個匹配資源的 URL。
cl.getResources(resourcePath) 返回 Enumeration<URL>,顯示所有版本位置-classloader 參數檢視特定載入器 (WebAppClassLoader 等)META-INF/MANIFEST.MF 顯示 Implementation-VersionNoSuchMethodError)java JWhich 可疑類別mvn dependency:tree / gradle dependencies 找出傳遞依賴來源<exclusion>) 或調整 Classpath 順序| 工具 | 特色 |
|---|---|
java -verbose:class | JVM 內建,啟動時印出所有載入類別來源 |
jcmd | JDK 內建,運行時查看載入器統計 |
| Arthas (Alibaba) | sc -d 類別名 顯示載入器、路徑、哈希、版本;jad 反編譯 |
| Maven Enforcer Plugin | 建構期禁止版本衝突 (banDuplicateClasses) |
| Gradle Dependency Insight | gradle dependencyInsight --dependency 群組:模組 |