首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Java只能在FileChannel.truncate上以可预见的方式失败?

为什么Java只能在FileChannel.truncate上以可预见的方式失败?
EN

Stack Overflow用户
提问于 2017-08-01 14:56:31
回答 1查看 892关注 0票数 4

我在Wildfly中运行了一个web应用程序,部分应用程序通过:File.createTempFile(...)使用一个临时文件。然后将该临时文件用作读-写java.io.RandomAccessFile流的目标文件。该RandomAccessFile的RandomAccessFile是与之交互的,并最终被截断(当我完成它时)。文件的某些部分通过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和常规窗口盒上运行这个程序,并且这个问题是可靠的重现性的。我认为一定有一些真正的滥用档案设施,但我感到困惑。

而且,这个异常在Linux机器上从未见过,截断是可靠的。没有文件锁定正在执行,这是唯一使用的文件,东西正在缓冲和写入通道,但没有什么非常奇怪的事情发生。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-01 19:54:32

我的问题似乎没有一个恰当的答案/解决方案,但由于链接@diginoise作为一条评论,我至少发现了一些细节,这些细节为问题提供了信息。

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

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

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

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

这种缓解功能没有抛出错误,它确实允许截断,也允许deleteOnExit,但这是一个短期的不可持续的解决方案。使用反射来调用可能不存在的方法并不是很好的做法,这取决于FileChannel实现。使用FilChannel的另一个实现,我可能会破坏放置在周围的从未被清理过的临时文件。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45441249

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档