Ошибка с NIO при попытке скопировать большой файл - PullRequest
5 голосов
/ 12 января 2011

У меня есть код для копирования файла в другое место.

public static void copyFile(String sourceDest, String newDest) throws IOException {

    File sourceFile = new File(sourceDest);
    File destFile = new File(newDest);
    if (!destFile.exists()) {
        destFile.createNewFile();
    }

    FileChannel source = null;
    FileChannel destination = null;
    try {
        source = new FileInputStream(sourceFile).getChannel();
        destination = new FileOutputStream(destFile).getChannel();
        destination.transferFrom(source, 0, source.size());
    } finally {
        if (source != null) {
            source.close();
        }
        if (destination != null) {
            destination.close();
        }
    }

}
}

При копировании небольших фрагментов, скажем, 300-400 Мб, все работает как по волшебству.Но когда я попытался скопировать файл размером 1,5 Гб, это не удалось.Стек:

Выполнено: 12.01.2011 11:16:36 Основной FileCopier SEVERE: Возникла исключительная ситуация при копировании файла.Попробуйте снова.java.io.IOException: ошибка карты в sun.nio.ch.FileChannelImpl.map (FileChannelImpl.java:748) в файле sun.nio.ch.FileChannelImpl.transferFromFileChannel (FileChannelImpl.java:527) в файле sun.nio.ch.Cile.transferFrom (FileChannelImpl.java:590) в FileCopier.copyFile (FileCopier.java:64) в FileCopier.main (FileCopier.java:27) Причина: java.lang.OutOfMemoryError: Ошибка карты в sun.nio.ch.FileChan.map0 (собственный метод) в sun.nio.ch.FileChannelImpl.map (FileChannelImpl.java:745) ... еще 4 УСТРОЙСТВА УСПЕШНО (общее время: 0 секунд)

У меня неттесно сотрудничал с NIO.Не могли бы вы помочь мне?Заранее большое спасибо.

Ответы [ 2 ]

5 голосов
/ 12 января 2011

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

Отображаемое в память ByteBuffers освобождает их отображение в финализаторе и освобождает место для новых отображений. Это очень некрасиво, но по крайней мере это работает. Будем надеяться, что они что-то сделали с этим в следующей итерации NIO.

2 голосов
/ 12 января 2011

Вы отображаете память в файл, но в 32-разрядной виртуальной машине Java (которую, я полагаю, вы используете) ограничено адресное пространство памяти, поэтому метод map не работает.Я не думаю, что вы можете отобразить более 1,3-1,4 ГБ данных на диске.Какой размер кучи вы используете?

Вы можете попробовать уменьшить размер кучи или использовать 64-битную JRE.В качестве альтернативы, не читайте файл, отображая его в память с помощью NIO.Вместо этого используйте традиционный способ буферизованного чтения и записи для чтения и записи данных из одного файла в другой.

...