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

标签 java file ioexception randomaccessfile filechannel

<分区>

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

进行读写映射

与文件的所有交互完成后,使用 fileChannel.truncate(size) 将文件截断为适当的大小。这是总是抛出 IOException 的地方
在 sun.nio.ch.FileDispatcherImpl.truncate0(本地方法)

IOException 消息是通用的:
java.io.IOException:无法对打开了用户映射部分的文件执行请求的操作

这是一个由同一进程显式创建的临时文件,在使用它期间它一直保持打开状态,可能只有几秒钟。谷歌搜索表明可能 AV 软件有该文件的句柄,或者其他一些应用程序正在使用它,但我已经尝试在具有不同配置的各种 VM 和常规 Windows 框上运行它,并且该问题可以可靠地重现。我认为肯定存在一些对文件工具的真正滥用,但我不知所措。

此外,这种异常在 Linux 机器上从未出现过,截断工作可靠。没有执行文件锁定,这是唯一在使用的文件,正在缓冲并写入 channel ,但没有发生任何奇怪的事情。

为了记录,我创建了一些示例测试应用程序来创建流、 channel 、临时文件、执行截断等,但我无法在独立应用程序中重现该问题。不幸的是,我不能直接分享源代码,所以我会尽力描述正在发生的事情,希望有人遇到过类似的事情并可以提供一些指导。

最佳答案

我的问题似乎没有正确的答案/解决方案,但至少我遇到了一些可以说明问题的细节,这要归功于作为评论发布的链接@diginoise。

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

最后,我认为答案很简单,当我处理完这些文件时不要尝试截断/删除它们,而是跟踪它们并在下次应用程序启动时处理它们,这样可以保证它们没有 Activity 内存映射。

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

在我实现下一次启动时处理文件的更永久修复之前,我选择了 manually unmap通过反射内存。

此缓解措施确实可以在不引发错误的情况下运行,它确实允许截断,并且确实允许 deleteOnExit,但这是一种短期的不可持续的解决方法。根据 FileChannel 实现,使用反射来调用可能不存在的方法不是好的做法。使用 FilChannel 的另一个实现,我可能已经破坏了永远不会被清理的临时文件。

关于java - 为什么 Java FileChannel.truncate 仅在 Windows 上可预见地失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45441249/

相关文章:

java - Spring Web Application - 如何从页面 Controller 到业务层

java - 将 JNA 指针从一个 Java 应用程序发送到另一个 Java 应用程序

javascript - 我可以使用任何 HTML 或 JavaScript API 在 input[type=file] 中获取文件的路径吗?

python - somefile.close 和 somefile.close() 之间的区别

java - 什么是NoSuchBeanDefinitionException,我该如何解决?

java - java正则表达式中捕获组

ruby - 用ruby写入文件的中间

java - Flying Saucer - 无法捕获 IOException 正在关闭流

java - 如果应打开纯文本消息,为什么 Javamail 会抛出 IOException?

java.io.IOException : Server returned HTTP response code: 403 for URL