2012-05-09 3 views
1

무한 루프에서 파일을 만들고 삭제하는 (이름이 변경되지 않음) 간단한 테스트를 작성했습니다. 시험은 초 (! 때로는 77,000 이상 반복)의 몇 실행 한 다음이 예외와 함께 실패 않습니다File.createNewFile() randomly fails

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

어떻게 이런 일이 가능 :

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) 

여기에 테스트 논리입니까? 삭제 호출이 실패하지 않습니다. 그것은 말할 것입니다. 따라서 삭제는 항상 성공하지만 createNewFile은 실패합니다.

DeleteFile을 기능 가까이에 삭제 파일을 표시 :이 MSDN는 Win32 API 함수 DeleteFile에 대한 말씀입니다. 따라서 파일의 마지막 핸들 닫을 때까지 파일 삭제가 발생하지 않습니다. 파일을 열려면 CreateFile에 대한 후속 호출은 ERROR_ACCESS_DENIED와 함께 실패합니다.

그래서 createNewFile은 파일을 닫지 않습니까? 오픈 JDK 소스 파일 폐쇄 된 것을 우리에게 알려줍니다

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

사람이 동작을 설명 할 수 있습니까?

+0

, 나는 명시 적으로 행동이라고 주장 http://stackoverflow.com/a/23697734/715269 – Gangnus

+0

@Gangnus 무작위. 그래서 : 아니오, 허가 문제가 아닙니다. –

+0

알겠습니다. 저는 여러분이 비슷한 문제의 해결책을 찾고 있었기 때문에 여기에 답을 달았습니다. 여러분의 것은 제가 읽은 페이지 중 하나였습니다. 해결책을 찾았을 때, 나는 미래에 누군가를 돕기위한 링크를 여기에 두었습니다. 귀하의 질문에 대한 답변이나 답변으로 의미가있는 것이 아니며 답변으로도 게시되지 않습니다. – Gangnus

답변

2

질문을 쓰는 동안 설명을 발견했습니다. 나는 내가 배운 것을 나누고 싶었 기 때문에 여전히 질문을 올렸다.

내 응용 프로그램 만 파일에 액세스하는 시스템의 프로세스가 아닙니다. 예를 들어, Windows Search Index Service는 인덱스에 추가하려고하기 때문에이 파일을 열 수 있습니다. 또는보기를 업데이트하는 경우 Windows 탐색기.

+1

귀하의 경우에는 귀하의 안티 바이러스 소프트웨어입니다 내기. 이런 종류의 일은 항상 av와 함께 발생합니다. –

+1

이전 Windows 콘텐트 인덱싱 서비스는이 영역에서 불쾌한 버그가있었습니다.디렉토리를 빠르게 생성하고 삭제하면 디렉토리 핸들 (아마도 FindFirstFile 사용)이 열리지 만 닫히지 않으면 아무 것도 할 수없는 좀비 디렉토리가 생깁니다. 좀비를 죽이는 유일한 방법은 인덱싱 서비스를 다시 시작하는 것입니다. – arx

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를 호출하기 전에 삭제에 의해 발표되어 있는지 확인합니다 이런 식으로.

+0

코드가 실패의 가능성을 낮추지 만 성공을 보장하지는 않습니다. 파일을 10ms 이상 열어 놓는 프로세스가 여전히있을 수 있습니다. –

+0

파일 삭제 명령은 OS에 주어 졌으므로,이 명령을 실행 한 후에 아무도이 명령을 차단해서는 안됩니다. –

+0

확신하고 싶다면, f.createNewFile()에서 java.io.IOException을 잡은 다음 다시 시도한 후 10ms를 기다리십시오. –

0

이 문제는 최근에 File.renameTo() 메서드로 경험 한 문제를 상기시켜줍니다. (... 그리고 그것은 작동)

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

이상한 해결 방법으로 System.gc()를 호출하고 다시 파일 이름을 바꾸는 시도하는 것입니다 : 그것은이다 인해 JVM에서이 버그 (?이었다).

확실하지 ... 그것은 당신의 문제에 링크를 가지고 있지만, 탐험의 가치가있을 수 있습니다

관련 문제