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

VSCode生成Jar包时如何添加assets文件夹并解决运行JNI报错

问题根因

两个问题存在关联:

  • assets资源文件夹未打入Jar:当前assets目录与src平级存放在项目根目录,不属于Java默认类路径扫描范围,无论手动执行打包命令还是使用构建工具,默认都不会收录该路径下的文件到Jar包中
  • 运行时抛出Error: A JNI error has occured...:绝大多数场景是代码中使用new File("assets/xxx")这类读取本地文件系统相对路径的方式加载资源,Jar运行时工作目录下找不到对应文件触发异常;剩余少量场景为Jar主类清单配置错误、依赖的本地动态库未正确加载、编译与运行的JDK版本不兼容导致
解决方案

第一步:调整资源目录位置(推荐规范做法)

将assets目录移动到类路径资源根目录下,符合Java项目的标准结构约定:

无构建工具的原生项目

调整后目录结构如下,让assets和源码包同属src路径下:

root/
+- src/
|  +- default-package/
|  |  +- .java 源码文件
|  +- assets/

Maven/Gradle项目

按标准结构放置资源文件,不需要额外配置就能自动打包:

root/
+- src/
|  +- main/
|     +- java/  # 存放所有.java源码文件
|     +- resources/
|        +- assets/  # 将原根目录的assets整体移动到此处

如果不想移动目录,Gradle可在build.gradle中添加如下配置,指定打包时收录根目录的assets:

jar {
    from 'assets' into 'assets'
}

Maven可在pom.xml的build节点添加资源配置:

<resources>
    <resource>
        <directory>assets</directory>
        <targetPath>assets</targetPath>
    </resource>
</resources>

第二步:修改资源加载逻辑

禁止使用本地文件相对路径读取资源,改用类加载器读取classpath内的打包资源,示例代码:

// 错误写法:依赖本地磁盘路径,Jar包内资源无法被该方式读取
// File assetFile = new File("assets/xxx.png");

// 正确写法:通过类加载器读取Jar内的classpath资源
// 普通类中使用
InputStream assetStream = getClass().getClassLoader().getResourceAsStream("assets/xxx.png");
// 静态方法/静态代码块中使用,将MainClass替换为你当前类的类名
InputStream assetStream = MainClass.class.getClassLoader().getResourceAsStream("assets/xxx.png");

第三步:JNI错误专项排查

完成上述两步后如果仍抛出JNI错误,按以下顺序检查:

  • 解压Jar包查看META-INF/MANIFEST.MF文件,确认Main-Class配置的主类全类名和实际代码中的主类完全一致,无拼写、包路径错误
  • 如果项目依赖本地动态库(.dll/.so等文件),不要将这类文件打进Jar,需放在Jar外的固定目录,启动时添加JVM参数指定库路径:java -Djava.library.path=动态库所在目录 -jar 你的jar包名.jar
  • 确认运行Jar的JRE/JDK大版本和编译时使用的JDK版本一致,比如用JDK17编译的Jar不要用JRE8运行
  • 手动打包时,先执行javac命令将所有.java文件编译为.class文件,再将assets目录整体复制到.class文件的输出根目录,最后再执行jar打包命令,避免编译输出目录缺文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 01:15:39