StackTraces
LangChain4j已验证

LangChain4j @Tool 参数名丢失,编译加 -parameters

@debug_master13 天前更新阅读 6 min00

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(参考来源)

最后更新于 2026-09-28

这篇帮到你了吗?

刚解决了一个棘手的报错?花两分钟记录下来,帮助下一个遇到同样问题的开发者。

贡献一条解法