2016-06-24 7 views
1

При отладке проблемы на работе я заметил, что попытка использовать MappedByteBuffer после открытия FileOutputStream для сопоставленных файл (файл, из которого был создан MappedByteBuffer по вызову FileChannel.map()), последовательно вызывает следующее исключение:Чтение из java.nio.MappedByteBuffer, когда FileOutputStream открыто для сопоставленного файла, вызывает ошибку «небезопасного доступа к памяти»

«Исключение в потоке» main «java.lang.InternalError: произошла ошибка в небезопасная операция доступа к памяти ".

Вот небольшой пример кода, я бросил вместе, что последовательно вызывает исключение:

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.

Мне кажется, что ошибка происходит из-за того, что ByteBuffer, который я вызываю .get() включен, сопоставляется памяти с тем же файлом, который я передал в FileOutputStream. Я предполагаю, что существует некоторая внутренняя защита, которая предотвращает чтение файлов с отображением памяти, если файл открыт, но я не могу понять, в чем причина этого.

Что является особенностью памяти ByteBuffers с отображением памяти, которая препятствует разрешению операции чтения при открытии файла FileOutputStream в файле? Мне очень интересно понять внутренности этого исключения. То, что меня тоже озадачивает, заключается в том, что, похоже, не существует аналогичной проблемы с открытием FileInputStream и чтением из него, когда FileOutputStream открыт для одного и того же файла, даже если это должно быть существенно функционально схожим (чтение из файла, который уже открыт для записи).

ответ

2

При создании сопоставления памяти вы производите отображение области файла в память.

Когда вы используете FileOutputStream, вы обрезаете файл, а область памяти, которую вы картировали, больше не существует.

Если вы не усекаете файл, он будет иметь размер, который вы дали ему, когда вы выполнили сопоставление.

+2

Вы абсолютно правы - это определенно то, что происходит. Я сделал еще один быстрый тест, в котором я передал флаг «append» в FileOutputStream, и проблема больше не возникает. –

 Смежные вопросы

  • Нет связанных вопросов^_^