2016-06-24 11 views
1

직장에서 문제를 디버깅하는 동안 FileOutputStream을 매핑 된 파일로 연 후 MappedByteBuffer를 사용하려고 시도했습니다. 파일 (FileChannel.map() 호출을 통해 MappedByteBuffer가 작성된 파일)이 일관되게 발생하면 다음 예외가 throw됩니다.매핑 된 파일에 대해 FileOutputStream이 열린 경우 java.nio.MappedByteBuffer에서 읽음으로 인해 "안전하지 않은 메모리 액세스"오류가 발생합니다.

"스레드의 예외"main "java.lang.InternalError : 오류가 발생했습니다. 안전하지 않은 메모리 액세스 작업 "이 발생합니다.

여기서 일관 예외를 트리거 I 함께 던져 작은 코드 샘플이다 :

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.nio.ByteBuffer; 
import java.nio.channels.FileChannel; 

public class SomeClass { 
    // make sure the test file is at least this size, or you'll get a "cannot 
    // extend file to required size" exception when creating the buffer 
    private static int bufferSize = 10; 

    public static void main(String[] args) throws Exception { 
     File file = new File("/tmp/someFile"); 

     FileInputStream fis = new FileInputStream(file); 
     ByteBuffer bb = getByteBuffer(fis); 

     // If you comment this out, the error goes away. 
     new FileOutputStream(file); 

     bb.get(); 
    } 

    private static ByteBuffer getByteBuffer(FileInputStream fis) throws Exception { 
     return fis.getChannel().map(FileChannel.MapMode.READ_ONLY, 
      fis.getChannel().position(), bufferSize); 
    } 
} 

상기 코드는 지속적으로 상기 예외가 발생되게한다. 이 오류는 "bb.get()"명령에서 발생하며 FileOutputStream을 여는 코드를 주석 처리하면 발생하지 않습니다.

.get()을 호출하는 ByteBuffer가 FileOutputStream에 전달 된 것과 동일한 파일에 메모리 매핑되어 있기 때문에 오류가 발생했습니다. 파일이 열리면 메모리 매핑 된 파일을 읽을 수 없게하는 내부 보호 장치가 있다고 추측합니다. 그러나 이유는 무엇인지 파악할 수 없습니다.

열려있는 FileOutputStream이 파일에 존재할 때 읽기 작업이 허용되지 않도록하는 메모리 매핑 된 ByteBuffers의 특별한 기능은 무엇입니까? 이 예외의 내부를 이해하는 데 관심이 많습니다. 나도 신비스럽게도, FileOutputStream이 동일한 파일에 대해 열려있을 때 FileInputStream을 열어 읽는 것과 비슷한 문제가없는 것처럼 보입니다. FileOutputStream은 본질적으로 매우 기능적으로 유사해야하지만 (이미 파일 쓰기 위해 열렸습니다).

답변

2

메모리 매핑을 만들면 파일 영역을 메모리에 매핑합니다.

FileOutputStream을 사용하면 파일을 자르므로 매핑 한 메모리 영역이 더 이상 존재하지 않습니다.

파일을 자르지 않으면 매핑을 수행 할 때 지정한 크기가됩니다.

+2

당신은 절대적으로 옳습니다. 이것은 분명히 일어나고있는 일입니다. FileOutputStream에 "append"플래그를 전달하고 문제가 더 이상 발생하지 않는 또 다른 빠른 테스트를 수행했습니다. –