File.createNewFile()随机失败(File.createNewFile(&#

2019-07-29 08:11发布

我已经建立一个简单的测试,创建和删除文件(名称不变)在一个无限循环。 该测试并运行了几秒钟(有时超过77000次迭代!),然后失败,出现此异常:

Exception in thread "main" java.io.IOException: Access is denied
        at java.io.WinNTFileSystem.createFileExclusively(Native Method)
        at java.io.File.createNewFile(Unknown Source)
        at DeleteTest.main(DeleteTest.java:11)

下面是测试逻辑:

final File f = new File(pathname);
while (true) {
    final boolean create = f.createNewFile();
    if (!create) {
        System.out.println("crate failed");
    } else {
        final boolean delete = f.delete();
        if (!delete) {
            System.out.println("delete failed");
        }
    }
}

这怎么可能? 删除通话不会失败。 它会告诉。 所以删除总是成功,但createNewFile失败。 这是MSDN说,关于Win32 API函数DeleteFile

该功能的DeleteFile标志着在近删除的文件。 因此,直到最后句柄文件被关闭,不会发生文件删除。 后续调用CreateFile打开文件失败并ERROR_ACCESS_DENIED。

所以createNewFile不关闭文件? OpenJDK的来源告诉我们,文件关闭:

JNIEXPORT jboolean JNICALL
Java_java_io_Win32FileSystem_createFileExclusively(JNIEnv *env, jclass cls,
                                                   jstring pathname)
{
    jboolean rv = JNI_FALSE;
    DWORD a;

    WITH_PLATFORM_STRING(env, pathname, path) {
        int orv;
        int error;
        JVM_NativePath((char *)path);
        orv = JVM_Open(path, JVM_O_RDWR | JVM_O_CREAT | JVM_O_EXCL, 0666);
        if (orv < 0) {
            if (orv != JVM_EEXIST) {
                error = GetLastError();

                // If a directory by the named path already exists,
                // return false (behavior of solaris and linux) instead of
                // throwing an exception
                a = GetFileAttributes(path);

                if ((a == INVALID_FILE_ATTRIBUTES) ||
                        !(a & FILE_ATTRIBUTE_DIRECTORY)) {
                    SetLastError(error);
                    JNU_ThrowIOExceptionWithLastError(env, path);
                }
            }
        } else {
            JVM_Close(orv);
            rv = JNI_TRUE;
        }
    } END_PLATFORM_STRING(env, path);
    return rv;
}

任何人都可以解释这种现象?

Answer 1:

我发现一个解释,而写的问题。 我还张贴的问题,因为我想和大家分享我学到了什么。

我的应用程序是不是系统访问文件的唯一进程。 Windows搜索索引服务,例如,因为它想将它添加到它的索引就可以打开该文件。 或Windows如果更新视图浏览器。



Answer 2:

试试这个:

final File f = new File("file");
    while (true) {
        final boolean create = f.createNewFile();
        if (!create) {
            System.out.println("crate failed");
        } else {
            final boolean delete = f.delete();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                System.out.println("...");
            }
            if (!delete) {
                System.out.println("delete failed");
            }
        }
    }

这样既保证了文件被删除调用createNewFile之前发布。



Answer 3:

这个问题让我想起了我与File.renameTo()方法最近经历的一个问题。 这是(是?)由于JVM这个错误:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213298

一个奇怪的解决方法是调用System.gc()和重试再次重命名文件(和它的作品...)。

不知道它与您的问题的链接,但它可能是值得探讨...



文章来源: File.createNewFile() randomly fails