Java 預設編譯不保留方法參數名。類文件裡方法的形參是
arg0、arg1,除非編譯時加了-parameters。LangChain4j 靠反射拿到的參數名,把 LLM 返回的 JSON 參數映射回@Tool方法實參。名字拿不到,映射就失敗:要麼參數是 null 卻不報錯,要麼在 agentic 的 sequential 流程裡拋MissingArgumentException。
Issue & Env(案發現場與環境)
- 業務場景:用 LangChain4j 的
@Tool讓模型調本地方法。參數名沒編譯進去,映射失敗。 - 症狀一(靜默):工具方法裡參數拿到 null 或預設值,業務結果不對,卻一個例外都不拋。
- 症狀二(顯式):在 agentic 的 sequential 流程裡,直接拋
MissingArgumentException。 - 環境:LangChain4j,JDK 17+,Maven 或 Gradle 構建。
StackTrace(堆疊日誌)
issue #3746 裡的報錯原文:
dev.langchain4j.agentic.agent.MissingArgumentException: Missing argument: inputAgentB
例外消息形態就是 Missing argument: <参数名>,參數名隨你的程式碼而變。這個類是 agentic 模塊的。純 @Tool 場景的典型表現不一樣:參數拿到 null,但完全不報錯,更難查。
Reproduce(復現程式碼)
一個帶參數的 @Tool 方法:
public class MathTools {
@Tool("两个整数相加")
public int add(int a, int b) {
return a + b;
}
}
編譯時沒加 -parameters。模型按 JSON 鍵值對傳參,比如 {"a":1,"b":2}。LangChain4j 想把名字映射回 a、b,反射卻只看到 arg0、arg1,映射不上,兩個參數都成了預設值。加法結果自然不對。
Root Cause(根因分析)
Java 預設丟棄參數名
Java 編譯預設不保留方法形參名。類文件裡方法參數表裡是 arg0、arg1。加 -parameters 才會寫入真實名字。源碼帶調試信息 -g 的特定情況另說,這裡不展開。
映射偏偏靠這個名字
LangChain4j 把 LLM 返回的工具調用參數(JSON,按名字的鍵值對)映射回 @Tool 方法實參,靠的就是反射拿到的參數名。名字丟了,映射鏈就斷了。
兩種症狀,一種更難查
參數名拿不到,映射不上,參數就是 null。靜默模式下模型和業務都在猜,誰都不報錯。在 agentic 的 sequential 流程裡,則會直接拋 MissingArgumentException,反而好定位。
顯式命名只能緩解
@V("topic")、@P(name = "...") 這類顯式命名能部分緩解。但底層沒參數名時依然會出問題。issue #6282 記錄了 @P(name) 在某些寫入路徑下被忽略的情況。
The Fix(解決方案)
1. Maven 加編譯參數
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
2. Gradle 加編譯參數
Groovy DSL:
tasks.withType(JavaCompile) {
options.compilerArgs << '-parameters'
}
Kotlin DSL:
tasks.withType<JavaCompile> {
options.compilerArgs.add("-parameters")
}
3. Spring Boot 工程最容易踩的地方
用 spring-boot-starter-parent 的工程,它預設已經開了 -parameters。一旦你自己覆蓋了 compiler 插件的設定,這個預設就可能丟。重點檢查這裡,別把預設設定蓋沒了。
4. IDE 編譯的詭異差異
IDE(IDEA「Build project」)預設不加 -parameters。會出現「命令行 mvn 打包正常、IDE 裡跑就參數為 null」的差異。同步 IDE 的編譯設置,或讓 IDE 走 Maven/Gradle 編譯。
5. 驗證
javap -p -v YourToolClass.class | grep -A2 MethodParameters
能看到真實參數名,說明生效了。
6. 兜底
給 @Tool 方法參數顯式命名(@P / @V),並在工具內部對 null 參數做校驗。早失敗,早發現。
小結
@Tool 參數名丟失,根子在編譯期。先給 Java 編譯加上 -parameters,再留意 Spring Boot 預設設定被覆蓋、IDE 編譯不生效這兩處坑。實在拿不準,就用 javap 看一眼類文件裡到底有沒有真實參數名。
References(參考來源)
- Fail fast on parameter name mismatches in sequential agentic system — langchain4j issue #3746github-issue
- @P(name) is ignored when agent arguments are written into the AgenticScope — langchain4j issue #6282github-issue
- Tools — LangChain4j 官方文檔langchain4j-docs
- javac 手冊(-parameters 選項)— Oracle Java SE 17official-docs
