工程裡同時存在兩個 LangChain4j 版本時,core 升級刪掉了某個類,上層集成還在引用它。編譯能過,跑起來才炸
NoClassDefFoundError,根子是依賴解析選中了不匹配的版本。用langchain4j-bom對齊穩定模塊,beta / 預覽模塊再顯式 pin 到同一版本號。
Issue & Env(案發現場與環境)
- 業務場景:基於 Quarkus 的項目用 quarkus-langchain4j。把
langchain4j-core從 1.0.0-beta2 升到 1.0.0-beta3 後,構建期報錯。 - 環境:JDK 17+,Maven 或 Gradle 管理依賴,core 與第三方集成各自聲明版本。
- 缺的類:
dev.langchain4j.model.chat.TokenCountEstimator。
StackTrace(堆疊日誌)
報錯原文(來自 issue #2873):
java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkiverse.langchain4j.deployment.AiServicesProcessor#watchResourceFiles threw an exception: java.lang.NoClassDefFoundError: dev/langchain4j/model/chat/TokenCountEstimator
at io.quarkiverse.langchain4j.deployment.LangChain4jDotNames.<clinit>(LangChain4jDotNames.java:49)
at io.quarkiverse.langchain4j.deployment.AiServicesProcessor.watchResourceFiles(AiServicesProcessor.java:942)
Reproduce(復現程式碼)
pom 裡 core 升了版本,集成模塊還停在舊的:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-core</artifactId>
<version>1.0.0-beta3</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>1.0.0-beta2</version>
</dependency>
mvn compile 不報錯。一跑起來,找類就失敗。
Root Cause(根因分析)
先解釋「編譯能過、運行才炸」。core 從 1.0.0-beta2 升到 1.0.0-beta3 時,TokenCountEstimator 被刪掉了。依賴 core 的上層模塊(這裡是 quarkus-langchain4j 的 deployment 層)仍在引用它。引用寫在字節碼裡,編譯期不會去校驗目標類在不在,於是沒報。等運行或構建期真要加載這個類,才拋 NoClassDefFoundError。
更深一層是依賴解析。工程裡只要出現兩個 langchain4j 版本,選誰由解析規則定。Maven 走 nearest-wins,聲明層級近的優先。Gradle 預設選最高版本。選中的那個不一定和所有模塊匹配。
langchain4j-bom 能把穩定模塊對齊。但 beta / 預覽模塊常常不在 BOM 管理範圍內,得自己顯式 pin 版本。這類問題在「core 版本 vs 第三方集成版本」混著用的時候尤其多。升級 core 前,先確認上層集成跟沒跟。
有一點要說清:官方沒把「BOM 覆蓋 beta 模塊」寫成承諾。這屬於社區說法,截至撰寫時未核實。
The Fix(解決方案)
用 BOM 統一版本。Maven 在 dependencyManagement 裡引 langchain4j-bom,版本與 core 一致。各 langchain4j 模塊只寫 groupId 和 artifactId,不寫 version:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>1.0.0-beta3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Gradle 用 platform 引同一份 BOM:
implementation(platform("dev.langchain4j:langchain4j-bom:1.0.0-beta3"))
implementation("dev.langchain4j:langchain4j-core")
implementation("dev.langchain4j:langchain4j-open-ai")
beta / 預覽模塊別指望 BOM。把它們的版本號都 pin 成同一個。
然後自查依賴樹,目標只有一個版本的 langchain4j-core:
mvn dependency:tree -Dincludes=dev.langchain4j
./gradlew dependencies | grep langchain4j
升級也有講究。core 的 patch / minor 版本也可能刪類。升級前先讀 release notes。真遇到 NoClassDefFoundError,先用 -verbose:class,或用 jarviz、IDE 定位這個類來自哪個 jar,再回查那個版本刪沒刪過它。
小結
編譯過、運行炸,多半是版本沒對齊。先確認依賴樹裡只有一個 core,再用 BOM 管住穩定模塊,beta 模塊手動 pin。升級前看 release notes,比出事再查省事。
References(參考來源)
- TokenCountEstimator class missing in langchain4j-core-1.0.0-beta3 — langchain4j issue #2873github-issue
- langchain4j-bom — Maven Centralmaven-central
- Introduction to the Dependency Mechanism(nearest-wins 與 dependencyManagement)— Maven 官方文檔official-docs
- Dependency Constraints and Conflicts — Gradle 官方文檔official-docs
