Java 为什么StandardOpenOption.DELETE\u在\u关闭时不删除FileChannel的源文件?
我们在Java中有一个底层方法,它应该在调用源文件的close方法时删除源文件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
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;
}
}
是的,事实上,我也读过那个文档,它并不保证它是关闭的。然而,我不明白为什么在这种简单的情况下它不能关闭。不,它不是由其他作家打开的。