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

JDK17下Spring Boot JAR中Paths.get()抛出FileSystemNotFoundException问题

问题解析:JAR内资源用Paths.get()抛出FileSystemNotFoundException的原因

核心原因

打包后的JAR本质是ZIP格式文件,内部资源的URI为jar:file:/xxx/app.jar!/path/to/resource.json,这类URI需要依赖**Zip文件系统(ZipFileSystem)**才能访问。但Paths.get(URI)不会自动创建并注册对应的ZipFileSystem实例,当ZipFileSystemProvider维护的filesystems哈希表中没有匹配该JAR的FileSystem时,就会抛出FileSystemNotFoundException。

细节拆解

  • IDE运行正常的逻辑:在编辑器中运行时,应用的类路径资源是存放在本地文件系统的目录中(未打包进JAR),资源URI为普通file://格式,直接对应本地文件路径,无需依赖ZipFileSystem,因此Paths.get可正常工作。
  • ZipFileSystem的注册机制:从JDK7开始,NIO通过文件系统Provider扩展访问不同类型的资源。ZipFileSystemProvider会缓存已打开的Zip文件系统实例到filesystems哈希表中,当调用Paths.get(jarURI)时,它只会查找已注册的FileSystem,不会自动创建新实例——这就是抛出异常的直接原因。
  • 手动创建FileSystem的作用:调用FileSystems.newFileSystem(jarURI, env)会显式创建对应JAR的ZipFileSystem,并将其注册到ZipFileSystemProvider的缓存中,后续Paths.get就能找到对应的FileSystem,从而正常访问JAR内资源。
  • InputStream方式的差异:原代码用InputStream读取资源是通过类加载器直接获取字节流,完全绕开了NIO的文件系统机制,不需要依赖ZipFileSystem,因此无论是否打包都能正常运行。

实用解决方案

方案1:确保ZipFileSystem存在后再获取Path

封装工具方法,先判断资源是否在JAR内,若则显式创建FileSystem:

import org.springframework.core.io.ClassPathResource;
import java.nio.file.FileSystems;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.net.URISyntaxException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class ResourcePathUtils {
    public static Path getJarResourcePath(String resourceName) throws URISyntaxException, IOException {
        ClassPathResource resource = new ClassPathResource(resourceName);
        URI uri = resource.getURI();
        
        if ("jar".equals(uri.getScheme())) {
            Map<String, String> env = new HashMap<>();
            env.put("create", "false"); // 不创建新文件,仅打开现有JAR
            FileSystems.newFileSystem(uri, env);
        }
        
        return Paths.get(uri);
    }
}

方案2:沿用Spring资源加载机制(更推荐)

直接利用ClassPathResource的输入流读取内容,无需依赖NIO文件系统,更符合Spring生态:

import org.springframework.core.io.ClassPathResource;
import java.nio.charset.StandardCharsets;
import java.io.IOException;

// 读取资源内容
String content = new String(
    new ClassPathResource(WAVEFORM_FILE_NAME).getInputStream().readAllBytes(),
    StandardCharsets.UTF_8
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 21:50:20