Я создал простой тест, который создает и удаляет файл (имя не меняется) в бесконечном цикле. Тест выполняется пару секунд (иногда более 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 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;
}
Кто-нибудь может объяснить такое поведение?