Вопрос по java, winapi – File.createNewFile () случайно завершается ошибкой

1

Я создаю простой тест, который создает и удаляет файл (имя не изменяется) в бесконечном цикле. Тест выполняется в течение нескольких секунд (иногда более 77 000 итераций!), А затем завершается неудачей с этим исключением:

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 APIDeleteFile:

The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed. Subsequent calls to CreateFile to open the file fail with ERROR_ACCESS_DENIED.

ТакcreateNewFile не закрывает файл? Исходный код openjdk говорит нам, что файлis закрыто:

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;
}

Кто-нибудь может объяснить это поведение?

stackoverflow.com/a/23697734/715269 Gangnus
@Gangnus, я прямо заявил, что поведение было случайным. Итак: нет, это не проблема разрешения. Eduard Wirch
Понимаю. Я оставляю здесь ответ только потому, что искал решение подобной проблемы, а ваша была одной из страниц, которые я прочитал, и когда я нашел решение, я разместил здесь ссылку, чтобы помочь кому-то в будущем. Это НЕ подразумевается как ответ или ответ на ваш вопрос, и также не публикуется как ответ. Gangnus

Ваш Ответ

3   ответа
2

ос, потому что я хотел поделиться тем, что я изучил.

Мое приложение не единственный процесс в системе, обращающийся к файлам. Служба индекса поиска Windows, например, может открыть этот файл, потому что она хочет добавить его в свой индекс. Или Windows Explorer, если он обновляет вид.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
0

с которой я недавно столкнулся при использовании метода File.renameTo (). Это (было?) Из-за этой ошибки в jvm:

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

Странный обходной путь - вызвать System.gc () и повторить попытку переименования файла (и это работает ...).

Не уверен, что это связано с вашей проблемой, но, возможно, стоит изучить ...

0

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.

Error: User Rate Limit Exceeded Eduard Wirch
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы