为什么Java FileChannel.truncate仅在Windows上可预测地失败?

DoomUs

我有一个在Wildfly中运行的Web应用程序,该应用程序的一部分通过以下方式使用临时文件:File.createTempFile(...)然后将该临时文件用作可读写java.io.RandomAccessFile流的目标文件。该RandomAccessFile的java.nio.channels.FileChannel是与之交互并最终被截断的内容(当我完成操作时)。文件的某些部分确实通过读写映射FileChannel.map()

与文件进行所有交互之后,使用将文件截断为适当的大小fileChannel.truncate(size)总是在这里抛出IOException
at sun.nio.ch.FileDispatcherImpl.truncate0(Native Method)

IOException消息是通用的:
java.io.IOException: The requested operation cannot be performed on a file with a user-mapped section open

这是一个由同一进程显式创建的临时文件,并且在使用该文件的过程中一直保持打开状态,可能只有几秒钟的时间。谷歌搜索表明也许AV软件可以处理文件,或者其他一些应用程序正在使用它,但是我尝试在具有不同配置的各种VM和常规窗口盒上运行它,并且该问题可以可靠地重现。我认为一定确实存在对File工具的滥用,但是我很茫然。

另外,在Linux机器上从未见过这种异常,因此截断工作可靠。没有执行任何文件锁定,这是唯一使用的文件,正在缓冲内容并将其写入通道,但是没有什么奇怪的事情发生。

作为记录,我已经创建了一些示例测试应用程序,它们创建了流,通道,临时文件,执行截断等操作,并且无法在独立应用程序中重现该问题。不幸的是,我无法直接共享源代码,因此我正在尽最大努力描述正在发生的事情,以期有人遇到类似情况并可以提供一些指导。

DoomUs

我的问题似乎没有适当的答案/解决方案,但是至少由于链接@diginoise作为评论,我至少遇到了一些详细信息,可以解决问题。

我收到异常是因为我试图截断一个文件,该文件的内存映射字节缓冲区仍处于“活动”状态。显然,用户没有办法手动取消映射/释放该内存上的Windows句柄(请参阅oracle的bug数据库中的JDK bug)。

最后,我认为答案只是不要在我处理完这些文件后尝试截断/删除这些文件,而是要跟踪它们并在下次应用程序启动时对其进行处理,以确保它们不会处于活动状态内存映射。

顺便说一句,File.deleteOnExit()在这些内存映射文件条件下a也会失败。

在我实现在下次启动时处理文件的更永久的修复方法之前,我选择了通过反射手动取消映射内存。

此缓解措施可以正常运行而不会引发错误,它确实允许截断,并且确实允许deleteOnExit,但这是短期的不可持续的解决方法。使用反射来调用可能不存在的方法(取决于FileChannel实现)不是一个好习惯。使用FilChannel的另一种实现,我可能会破坏临时文件,这些临时文件永远都不会被清除。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Java的FileChannel.size()VS File.length() - FileChannel.truncate后()

为什么Java中的FileChannel不是非阻塞的?

使用 java nio 从 FileChannel 读取

Java FileChannel 保持锁定文件

为什么没有将缓冲区写入FileChannel

为什么BufferedWriter不通过打开的FileChannel写入文件?

为什么fileChannel.read循环永远不会结束?

为什么 FileChannel 不附加到文件末尾?

内置库可持久保存BTree,相当于Java的FileChannel和ByteBuffer

为什么我们从Java 1.6中的FileChannel.map获取ClosedByInterruptException?

Windows中大文件的FileChannel.transferTo

Java NIO中FileChannel.read()/ write()的模棱两可和令人困惑的命名

什么时候使用FileChannel读取()/ write()文件?

为什么nio.files.copy比nio.fileChannel复制慢很多?

Java NIO FileChannel与FileOutputstream的性能/有用性

Java:创建支持字节数组的FileChannel

为什么Java不允许在迭代器上使用foreach(仅在可迭代对象上)?

如果仍然抛出OverlappingFileLockException,则在FileChannel.lock中等待的目的是什么?

为什么Java stacktrace仅在finally块中返回失败?

Java:如何定义缓冲区大小以从FileChannel读取所有数据

如何使用java.nio.channels.FileChannel读取ByteBuffer实现类似BufferedReader#readLine()的行为

如何从使用Java中的FileChannel映射的内存中取消映射文件?

当相应的Stream关闭时,Java FileChannel锁是否关闭了?还是必须显式关闭它们?

Java:将FileChannel和ByteChannel一起使用时,READ和WRITE是“模糊的”?

在OSX和JVM 7上,FileChannel.open似乎已损坏

为什么在Java中使用HashMap失败?

为什么握手失败(Java SSL)

Java分解失败-为什么循环?

为什么Java枚举不是可克隆的?