You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于AsyncHttpClient的Java Maven项目运行JNI错误排查求助

解决Maven项目运行时的NoClassDefFoundError问题

错误原因分析

你遇到的java.lang.NoClassDefFoundError: org/asynchttpclient/AsyncHandler错误,本质是因为你打包生成的JAR只包含了你自己编写的代码,没有把项目依赖的AsyncHttpClient等第三方库打包进去。当Java运行时尝试加载这些依赖类时,找不到对应的class文件,就会抛出这个错误。

解决方案:打包包含所有依赖的可执行JAR

Maven默认的package命令只会生成只含自身代码的JAR,我们需要用Maven插件来构建包含所有依赖的"胖JAR"(Fat JAR)。这里推荐两种常用的插件:

1. 使用Maven Shade Plugin(推荐)

Shade插件不仅会打包所有依赖,还能处理可能的类冲突,是比较常用的选择。在你的pom.xml中添加以下插件配置:

<build>
    <plugins>
        <!-- 配置Shade插件构建可执行胖JAR -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.5.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <!-- 指定主类,也就是你项目的入口类 -->
                        <mainClass>me.company.MyProject.App</mainClass>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>me.company.MyProject.App</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

添加完成后,重新执行Maven的package命令:

mvn clean package

执行完成后,在target目录下会生成两个JAR:

  • MyProject-0.0.1-SNAPSHOT.jar:默认的轻量JAR(不含依赖)
  • MyProject-0.0.1-SNAPSHOT-shaded.jar:包含所有依赖的可执行胖JAR

运行这个胖JAR即可:

java -jar .\MyProject-0.0.1-SNAPSHOT-shaded.jar

2. 使用Maven Assembly Plugin

如果你更倾向于另一种方式,也可以用Assembly插件。在pom.xml中添加:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.6.0</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifest>
                        <mainClass>me.company.MyProject.App</mainClass>
                    </manifest>
                </archive>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

同样执行mvn clean package,然后运行生成的MyProject-0.0.1-SNAPSHOT-jar-with-dependencies.jar:

java -jar .\MyProject-0.0.1-SNAPSHOT-jar-with-dependencies.jar

额外代码优化提示

你编写的AsyncHandler实现有个小问题:onStatusReceived、onHeadersReceived、onBodyPartReceived方法返回的是null,这会导致运行时异常。根据AsyncHttpClient的要求,这些方法需要返回一个State枚举值,比如State.CONTINUE表示继续处理响应,State.ABORT表示中止处理。修改后的代码示例:

postRequest.execute(new AsyncHandler<Object>() {
    public State onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
        System.out.print("\nstatus received: " + responseStatus.getStatusCode());
        return State.CONTINUE; // 必须返回有效的State值
    }
    public State onHeadersReceived(HttpHeaders headers) throws Exception {
        System.out.print("\nheaders received");
        return State.CONTINUE;
    }
    public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
        System.out.print("\nbody part received");
        return State.CONTINUE;
    }
    public void onThrowable(Throwable t) {
        t.printStackTrace(); // 建议添加异常打印,方便排查问题
    }
    public Object onCompleted() throws Exception {
        System.out.print("\nexecute completed");
        return null;
    }
});

另外,注意不要在发送异步请求后立即关闭client,因为异步请求还没完成就关闭客户端会导致请求失败。应该在请求完成后(比如onCompleted或onThrowable方法中)关闭客户端,或者使用try-with-resources来管理:

try (AsyncHttpClient client = Dsl.asyncHttpClient()) {
    // 构建并执行请求
    BoundRequestBuilder postRequest = client
            .preparePost("http://localhost:8080/my_custom_url/")
            .addFormParam("id", myid)
            .addFormParam("stream", inData);
    
    postRequest.execute(new AsyncHandler<Object>() {
        // 实现方法...
        public Object onCompleted() throws Exception {
            System.out.print("\nexecute completed");
            return null;
        }
    }).toCompletableFuture().join(); // 如果需要等待请求完成,可使用join()
} catch (IOException e) {
    // 处理异常
}

这样可以避免因提前关闭客户端导致的请求失败问题。

内容的提问来源于stack exchange,提问作者JumpingElephant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:25:01