FileOutputStream 的 try-with-resources 不会关闭文件描述符

7
我有一些代码,可以将某个特定的大型(约15k条目)二进制序列化文件归档提取到磁盘上的文件夹中。
public void extractExact(Path absolutePath, DoubleConsumer progressConsumer) throws IOException
{
    ...
    // Extract to file channel
    try (final FileOutputStream fos = new FileOutputStream(absolutePath.toFile()))
    {
        PakExtractor.Extract(pakFile, Entry, fos.getChannel(), progressConsumer);
    }
 }

extractExact函数对归档文件中的每个条目进行调用。

之后,如果我尝试调用Files.delete(<archive_file_path>)方法 - 我会得到一个异常:

java.nio.file.FileSystemException: 由于另一个进程正在使用这个文件,因此无法访问该文件。

我在Process Explorer中搜索我的归档文件,并发现我的java.exe有大约15k个文件打开(与归档文件中的文件数量一样多)。

这只发生在Windows上(jdk1.8.0_162)。在Linux上,我没有任何“僵尸”打开的文件问题。


可能是Windows中的某些服务在索引/分析文件吗?例如桌面搜索索引、杀毒软件等? - NeplatnyUdaj
1
在下一次调用之前,您可能需要调用 fos.flush() ?这可能是因为仍然有要写的内容。 - Sascha
你的try-with-resources用法是正确的。我多次观察到Windows在程序关闭文件后仍会保持对该文件的锁定,即使是非Java程序(但我很难找到一个现有的Stack Exchange问题与此相关)。 - VGR
3
дёәд»Җд№ҲиҰҒз»•иҝңи·Ҝе‘ўпјҹеҸӘйңҖдҪҝз”Ёtry(FileChannel ch = FileChannel.open(absolutePath, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) { вҖҰ }еҚіеҸҜпјҢдёҚйңҖиҰҒдҪҝз”Ё.toFile()е’Ң.getChannel()гҖӮеҰӮжһңжӮЁжғійҡҸеҗҺеҲ йҷӨиҜҘж–Ү件пјҢеҸҜд»ҘеңЁopenи°ғз”ЁдёӯжҢҮе®ҡStandardOpenOption.DELETE_ON_CLOSEгҖӮ - Holger
1
断点应该在你的 tryfinally 部分。 - Sascha
显示剩余4条评论
1个回答

3

终于找到了解决方案。非常感谢@Netherwire的帮助。FileChannel类有一个map方法,它会对文件描述符进行一些隐式的复制操作,因此在使用时要小心。 这里有更多信息。


1
我遇到了一些场景,其中我使用了在我的先前评论中提到的DELETE_ON_CLOSE选项和map。好处是,当仍然存在映射阻止在close()时间删除文件时,文件将在映射被清除或在JVM退出时间作为最后手段时被删除。 - Holger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接