我有一个在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机器上从未见过这种异常,因此截断工作可靠。没有执行任何文件锁定,这是唯一使用的文件,正在缓冲内容并将其写入通道,但是没有什么奇怪的事情发生。
作为记录,我已经创建了一些示例测试应用程序,它们创建了流,通道,临时文件,执行截断等操作,并且无法在独立应用程序中重现该问题。不幸的是,我无法直接共享源代码,因此我正在尽最大努力描述正在发生的事情,以期有人遇到类似情况并可以提供一些指导。
我的问题似乎没有适当的答案/解决方案,但是至少由于链接@diginoise作为评论,我至少遇到了一些详细信息,可以解决问题。
我收到异常是因为我试图截断一个文件,该文件的内存映射字节缓冲区仍处于“活动”状态。显然,用户没有办法手动取消映射/释放该内存上的Windows句柄(请参阅oracle的bug数据库中的JDK bug)。
最后,我认为答案只是不要在我处理完这些文件后尝试截断/删除这些文件,而是要跟踪它们并在下次应用程序启动时对其进行处理,以确保它们不会处于活动状态内存映射。
顺便说一句,File.deleteOnExit()
在这些内存映射文件条件下a也会失败。
在我实现在下次启动时处理文件的更永久的修复方法之前,我选择了通过反射手动取消映射内存。
此缓解措施可以正常运行而不会引发错误,它确实允许截断,并且确实允许deleteOnExit,但这是短期的不可持续的解决方法。使用反射来调用可能不存在的方法(取决于FileChannel实现)不是一个好习惯。使用FilChannel的另一种实现,我可能会破坏临时文件,这些临时文件永远都不会被清除。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句