FileSystems.getDefault() 返回 JVM 当前环境下的默认文件系统实例,由 SPI 机制动态加载,首次调用初始化并缓存,后续返回同一单例;其具体实现类(如 WindowsFileSystem、LinuxFileSystem)取决于底层 OS 和系统属性配置,均基于 "file" 方案。

FileSystems.getDefault() 返回的是 JVM 当前环境下的默认文件系统实例,它不是硬编码的类,而是由 Java 的服务发现机制(SPI)和系统属性共同驱动的动态加载结果。其具体实现类在不同操作系统下可能相同,也可能不同,关键不在于“操作系统类型”,而在于 Java 运行时如何选择并初始化 FileSystemProvider。
默认提供者(Default Provider)的加载逻辑
Java 通过 java.nio.file.spi.FileSystemProvider 的 SPI 机制加载文件系统提供者。默认情况下:
- 若未设置系统属性
java.nio.file.spi.DefaultFileSystemProvider,则使用 JVM 自带的 系统默认提供者 —— 即SunFileSystemProvider(在 OpenJDK 中实际为WindowsFileSystemProvider、UnixFileSystemProvider或MacOSXFileSystemProvider,取决于底层 OS); - 该提供者由
FileSystem.getFileSystem(URI.create("file:///"))创建,默认文件系统 URI 固定为file:///; - 所有平台的默认文件系统都基于
"file"方案,与操作系统的路径分隔符(\vs/)、大小写敏感性、权限模型等差异无关,这些由具体 Provider 实现内部处理。
操作系统相关实现类的典型对应关系
虽然用户代码无需关心具体类名,但了解其实现有助于调试和定制:
-
Linux / macOS:通常加载
sun.nio.fs.LinuxFileSystemProvider或sun.nio.fs.BsdFileSystemProvider(macOS 属于 BSD 衍生),最终返回LinuxFileSystem或BsdFileSystem实例; -
Windows:加载
sun.nio.fs.WindowsFileSystemProvider,返回WindowsFileSystem; - 同一 JDK 版本下,类名不随用户切换操作系统而改变 —— JVM 启动时已根据 native 层判断 OS 类型,并绑定对应 provider;
- 这些类均位于
jdk.internal.jrtfs或java.base模块内,不可直接 new,仅通过FileSystems.getDefault()获取。
自定义默认文件系统的两种方式
如需替换默认行为(例如嵌入式场景或测试隔离),可通过以下任一方式干预:
-
设置系统属性:
-Djava.nio.file.spi.DefaultFileSystemProvider=your.package.YourFileSystemProvider,要求该类:- 有且仅有一个接受
FileSystemProvider参数的构造器; - 方案名(scheme)必须为
"file"(大小写敏感); - 按顺序链式委托前一个 provider(最后一个被实例化的才是最终默认)。
- 有且仅有一个接受
- 替换 classpath 中的 provider 实现(不推荐生产环境):将自定义 provider JAR 放入 boot classpath,覆盖默认实现 —— 此方式绕过 SPI,风险高且破坏模块封装。
为什么 FileSystems.getDefault() 是线程安全且单例的?
该方法首次调用时完成 provider 查找、实例化与文件系统创建;后续调用直接返回缓存引用。整个过程受内部锁保护,且返回的 FileSystem 实例本身是无状态的(路径解析、属性读取等操作不修改其字段),因此天然支持多线程并发访问。











