Файловый канал Java 7 не закрывается должным образом после вызова метода карты

Я работаю над инструментом синтаксического анализа sc2replay. Я создаю его поверх MPQLIB http://code.google.com/p/mpqlib/

К сожалению, инструмент использует файловые каналы для чтения файлов bzip и использует map(MapMode.READ_ONLY, hashtablePosition, hashTableSize);

После вызова этой функции закрытие файлового канала не освобождает файл в процессе. Если быть точным, я не могу переименовать/переместить файл.

Проблема возникает в Java 7 и отлично работает в Java 6.

Вот простой фрагмент кода для его воспроизведения:

    FileInputStream f = new FileInputStream("test.SC2Replay");
    FileChannel fc = f.getChannel();

    fc.map(MapMode.READ_ONLY, 0,1);

    fc.close();

    new File("test.SC2Replay").renameTo(new File("test1.SC2Replay"));

комментирование fc.map позволит вам переименовать файл.

P.S. отсюда Должен ли я закрыть FileChannel?

В нем говорится, что вам не нужно закрывать и файловый канал, и файловый поток, потому что закрытие одного приведет к закрытию другого. Я также пытался закрыть один или оба, но все равно не работал.

Есть ли обходной путь для переименования файла после чтения данных с помощью FileChannel.map на Java 7, потому что в настоящее время у всех есть Java 7?


person Community    schedule 25.10.2012    source источник
comment
Вызывает ли закрытие канала или потока какое-то RuntimeException?   -  person 0xCAFEBABE    schedule 25.10.2012
comment
исключение не генерируется. Я думаю, что это может быть ошибка самой Java 7. Я думаю портировать все на .NET xD   -  person    schedule 25.10.2012


Ответы (3)


Добрый день,

кажется, что FileChannel.map вызывает проблему на java 7. если вы используете FileChannel.map, вы больше не можете закрыть файл.

быстрый обходной путь вместо использования FileChannel.map(MapMode.READ_ONLY, position, length)

ты можешь использовать

ByteBuffer b = ByteBuffer.allocate(length); 
fc.read(b,position);
b.rewind();
person Community    schedule 25.10.2012

Это задокументированная ошибка. Отчет об ошибке относится к Java 1.4, и они считают это ошибкой документации. Закрытие файлового канала не закрывает базовый поток.

person 0xCAFEBABE    schedule 25.10.2012
comment
@tskaahyeah Упомянутый здесь отчет об ошибке сомнительный и помечен как «невозможно воспроизвести». Закрытие FileChannel закрывает базовый дескриптор файла: я читал исходный код ранее на этой неделе. Проблема здесь в том, что закрытие файла сопоставления не освобождает сопоставление. - person user207421; 25.10.2012
comment
сверху я попытался закрыть как файловый канал, так и файловый входной поток, а также попытался закрыть только файловый входной поток и закрыть только файловый канал. Все не работало. код хорошо работает на java6, но не на java7 - person ; 25.10.2012

Если вы используете Sun JRE, вы можете схитрить, приведя к их реализации и сказав ей выпустить себя. Я бы рекомендовал делать это только в том случае, если вы не зависите от закрытия файла или никогда не планируете использовать другую JRE.

Я надеюсь, что в какой-то момент что-то подобное станет полноценным общедоступным API.

try (FileInputStream stream = new FileInputStream("test.SC2Replay");
     FileChannel channel = stream.getChannel()) {

    MappedByteBuffer mappedBuffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, 1);
    try {
        // do stuff with it
    } finally {
        if (mappedBuffer instanceof DirectBuffer) {
            ((DirectBuffer) mappedBuffer).cleaner().clean();
        }
    }
}
person Trejkaz    schedule 18.08.2015