JDK 自带的 zip 文件系统让 zip 与 jar 像目录一样用 Files 和 Path 操作。这篇逐项真实运行:创建、列出、修改、何时写盘、多版本 jar 的 releaseVersion 与重复打开。
在 zip 文件系统里创建后、close() 之前,磁盘上的 a.zip 是否存在:true,大小 22 字节
fs.provider().getScheme() = jar,isReadOnly = false,根目录 = /,separator = /
close() 之后 a.zip 存在,大小 743 字节
Files.walk 看到:[/, /bin.dat, /docs, /docs/readme.txt, /docs/sub, /docs/sub/中文.txt]
readme.txt 大小 2400 字节,isDirectory = false;读出前 12 字符「hello zipfs」;中文文件名读出:你好
关闭之后再用 Path → ClosedFileSystemException
用 Python zipfile 读同一个文件验证: [('docs/', 0, 0, 0), ('docs/sub/', 0, 0, 0), ('docs/readme.txt', 2400, 34, 8), ('docs/sub/中文.txt', 6, 8, 8), ('bin.dat', 1000, 11, 8)]生成 200 个各 256 KB 随机内容的条目,zip 大小 50 MB 默认(堆里缓存)往已有 50 MB 的 zip 里加一个 10 字节的条目:打开 0 ms;close() 耗时 53 ms;这个线程分配 599 KB;close 之前磁盘文件的修改时间没变 = true;close 之后文件大小 52471559 字节(之前 52471402) close 前后 a.zip 的 fileKey 是否相同(同一个 inode)= false(true 表示原文件被就地改写,false 表示换了新文件) 默认 往 50 MB 的 zip 里写 40 个 256 KB 的条目(共 10 MB)后、close 之前做一次 GC,文件系统还开着时多占的堆:0 MB;整个过程(含 close)67 ms useTempFile=true 往 50 MB 的 zip 里写 40 个 256 KB 的条目(共 10 MB)后、close 之前做一次 GC,文件系统还开着时多占的堆:0 MB;整个过程(含 close)75 ms 4 MB 全零:noCompression=true 时 zip 4194462 字节;默认(压缩)4238 字节
jar 里有 /lib/Impl.class jar 里有 /META-INF/versions/21/lib/Impl.class jar 里有 /META-INF/versions/17/lib/Impl.class jar 里有 /META-INF/MANIFEST.MF releaseVersion=8:读 /lib/Impl.class 得到 264 字节(版本化条目大小不同,说明取到了对应版本) releaseVersion=17:读 /lib/Impl.class 得到 298 字节(版本化条目大小不同,说明取到了对应版本) releaseVersion=21:读 /lib/Impl.class 得到 322 字节(版本化条目大小不同,说明取到了对应版本) releaseVersion=runtime:读 /lib/Impl.class 得到 322 字节(版本化条目大小不同,说明取到了对应版本) 同一个 jar 同时用 newFileSystem(Path) 打开两次 → 成功(两个独立实例) 用 jar: URI 打开同一个 jar 第二次 → FileSystemAlreadyExistsException FileSystems.getFileSystem(uri) 得到的与 f1 是同一个对象 = true