【问题标题】:FileUtils.moveFile not always throwing IOException when disk is fullFileUtils.moveFile 在磁盘已满时并不总是抛出 IOException
【发布时间】:2017-05-28 12:29:37
【问题描述】:

FileUtils.moveFile 在磁盘已满情况下无法移动失败时并不总是抛出 IOException。新文件已创建,但大小为 0。下面是代码

void  function1 (String filePath1, String dir) 
{
    File file1= new File( filePath1);
    File file2= new File( dir, file1.getName() );
    
    FileUtils.moveFile( file1, file2);
}

多个线程正在使用上述函数。每个线程都有一个唯一的 filePath1 值。磁盘存储由 NFS 服务器控制。因此,当移动文件失败并创建空文件时,一些线程会抛出以下异常(文件名已被屏蔽)。

无法将完整内容从“######”复制到“######”预期长度:239?实际:0

在 org.apache.commons.io.FileUtils.doCopyFile(FileUtils.java:1164)

在 org.apache.commons.io.FileUtils.copyFile(FileUtils.java:1088)

在 org.apache.commons.io.FileUtils.copyFile(FileUtils.java:1040)

在 org.apache.commons.io.FileUtils.moveFile(FileUtils.java:2993)

在函数1

但是其中一些没有抛出任何异常,并且目标文件是空的。

为了验证这一点,我添加了文件大小检查。

void  function1 (String filePath1, String dir)
{
    File file1= new File( filePath1);
    File file2= new File( dir, file1.getName() );
    long sizeOfFile1 = FileUtils.sizeOf( file1);
    FileUtils.moveFile( file1, file2);
    long sizeOfFile2 = FileUtils.sizeOf( file2);

    if( sizeOFile1 != sizeOfFile2 )
          LOG.error( "###### expected size " + sizeOFile1 + " but actual size " +  sizeOfFile2 + " for thread " + ######## );
        throw new IOException();

    }
}

在此之后,之前没有抛出异常的每个线程都开始在上面的函数中打印错误

线程的预期大小为 239,但实际大小为 0

所以我想了解在 NFS 存储的情况下是否还有其他事情可以完成,或者 JVM 中是否存在错误,导致它在移动文件失败时没有通知应用程序?

【问题讨论】:

  • 检查这个:stackoverflow.com/questions/1051295/… File 类有一些检查磁盘空间的方法
  • 使用 java.nio.file.Files
  • 感谢链接。但该程序的目标不是检测磁盘何时已满。这里的问题是 FileUtils.moveFile 函数在移动文件失败时并不总是抛出 IOException。在一个线程中它会抛出异常,而在另一个线程中则不会。在两个线程中,目标文件都是空的。
  • @rkosegi:在“FileUtils.moveFile”的描述中,它被写成“IOException - 如果移动文件时发生 IO 错误”并且它正在其中一个线程中抛出。在 java.nio.file.Files.move 函数“IOException - 如果发生 I/O 错误”的描述中也是如此。所以我想了解为什么它并不总是有效。
  • FileUtils 是哪个版本的?你能指定maven依赖吗?例如,<groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>1.3.2</version> 提供 FileUtils.copyFile( file1, file2),它比较文件大小并可能相应地抛出 IOException。

标签: java multithreading ioexception


【解决方案1】:

write(...) 系统调用对完整文件系统的正常行为是失败并将errno 设置为ENOSPC。然后 Java 会将其转换为 IOException

但是,您的 NFS 挂载似乎没有像普通文件系统那样报告文件系统已满。以下是可能发生这种事情的一些证据:

如果写入系统调用未报告错误,则 Java 运行时无法检测问题。如果这是正在发生的事情,那么它就不是 Java 错误。这可能是您正在使用的 NFS 服务器或客户端实现中的一个错误。


我希望FileUtils.moveFilecopyFile 方法能够检测到问题。但是你没有说你使用的是哪个版本的 Apache Commons,所以我不能确定。此外,由于您使用多个线程来移动文件,因此两个线程可能正在尝试移动同一个文件,这会导致问题。

【讨论】:

  • 有趣的 NFS 问题记录。太糟糕了,它基于从localhost 共享的文件的 NFS 挂载 - 如果您将其报告为错误,则不会真正支持。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-05
  • 1970-01-01
  • 2015-06-21
  • 2018-12-31
  • 1970-01-01
相关资源
最近更新 更多