Java 为什么StandardOpenOption.DELETE\u在\u关闭时不删除FileChannel的源文件?

Java 为什么StandardOpenOption.DELETE\u在\u关闭时不删除FileChannel的源文件?,java,filechannel,nio2,autocloseable,Java,Filechannel,Nio2,Autocloseable,我们在Java中有一个底层方法,它应该在调用源文件的close方法时删除源文件 private void appendFile(Path destination, Path source) {     try (FileChannel sourceChannel = FileChannel.open(source, StandardOpenOption.READ, StandardOpenOption.DELETE_ON_CLOSE);          FileChannel destina

我们在Java中有一个底层方法,它应该在调用源文件的close方法时删除源文件

private void appendFile(Path destination, Path source) {

    try (FileChannel sourceChannel = FileChannel.open(source, StandardOpenOption.READ, StandardOpenOption.DELETE_ON_CLOSE);
         FileChannel destinationChannel = FileChannel.open(destination, StandardOpenOption.WRITE, StandardOpenOption.APPEND)) {
        destinationChannel.transferFrom(sourceChannel, destinationChannel.size(), sourceChannel.size());
    } catch (IOException ex) {
       // Do something with this exception
    }
}
现在,我们对此运行一个功能集成测试,并看到源文件没有被删除


有人能帮我们吗?

来自
StandardOpenOption。删除\u ON\u CLOSE
选项文档:

如果存在此选项,则实现会产生最佳效果 尝试在关闭时通过相应的关闭按钮删除文件 方法。如果未调用close方法,则会进行最大努力尝试 用于在Java虚拟机终止时删除文件 (通常情况下,如Java语言规范所定义,或 在可能的情况下,不正常地)

此选项主要用于 使用仅由单个Java实例使用的工作文件 虚拟机。打开时不建议使用此选项 由其他实体同时打开的文件。许多 有关何时以及如何删除文件的详细信息,请参阅实现 具体的,因此没有具体说明。特别是一个实现 可能无法保证在以下情况下删除所需的文件: 文件打开时被攻击者替换。因此,安全 使用此选项时,敏感应用程序应小心


因此,这只是尽最大努力,而不是100%保证它会被删除。也许它还被其他作者打开了?

在Win7/x64上的一个用户定期发现程序终止后未删除的遗留文件后,我们在2015年左右遇到了类似的问题。经过一些研究和反复试验,我们发现这种情况只发生在最近被内存映射的文件上,并通过避免在我们希望很快/稍后删除的文件上进行内存映射来修复这种情况

FileChannelImpl.transferFromFileChannel
内存映射要传输的源。(取决于你的JVM——我是基于OpenJDK的。)当JVM在复制后通过取消映射进行清理,从而使创建的视图无效时,操作系统可能会将实际清理延迟到另一个时间点。在此之前,该文件有一个活动(但不可访问)内存映射,可能会阻止取消链接

这个问题似乎与:

供参考:jdk11/sun.nio.ch.FileChannelImpl#transferFromFileChannel

private long transferFromFileChannel(FileChannelImpl src,
                                     long position, long count)
    throws IOException
{
    if (!src.readable)
        throw new NonReadableChannelException();
    synchronized (src.positionLock) {
        long pos = src.position();
        long max = Math.min(count, src.size() - pos);

        long remaining = max;
        long p = pos;
        while (remaining > 0L) {
            long size = Math.min(remaining, MAPPED_TRANSFER_SIZE);
            // ## Bug: Closing this channel will not terminate the write
            MappedByteBuffer bb = src.map(MapMode.READ_ONLY, p, size);
            try {
                long n = write(bb, position);
                assert n > 0;
                p += n;
                position += n;
                remaining -= n;
            } catch (IOException ioe) {
                // Only throw exception if no bytes have been written
                if (remaining == max)
                    throw ioe;
                break;
            } finally {
                unmap(bb);
            }
        }
        long nwritten = max - remaining;
        src.position(pos + nwritten);
        return nwritten;
    }
}

是的,事实上,我也读过那个文档,它并不保证它是关闭的。然而,我不明白为什么在这种简单的情况下它不能关闭。不,它不是由其他作家打开的。