Как избежать OutOfMemoryError при использовании Bytebuffers и NIO?

StackOverflow https://stackoverflow.com/questions/28675

Вопрос

Я использую ByteBuffers и FileChannels для записи двоичных данных в файл.Делая это для больших файлов или последовательно для нескольких файлов, я получаю OutOfMemoryError исключение.Я читал в другом месте, что использование Bytebuffers with NIO нарушен, и его следует избегать.Кто-нибудь из вас уже сталкивался с подобной проблемой и нашел решение для эффективного сохранения больших объемов двоичных данных в файле на java?

Это вариант jvm -XX:MaxDirectMemorySize как нам поступить?

Это было полезно?

Решение

Я бы сказал, не создавайте огромный ByteBuffer, который содержит ВСЕ данные сразу.Создайте байтбуфер гораздо меньшего размера, заполните его данными, затем запишите эти данные в файловый канал.Затем сбросьте байтбуфер и продолжайте до тех пор, пока не будут записаны все данные.

Другие советы

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

Единственные две уловки, которые я могу придумать, это:

  1. В 32-разрядной системе ваш объем ограничен чуть менее 4 ГБ итого для всех сопоставленных байтовых буферов.(На самом деле это ограничение для моего приложения, и теперь я работаю на 64-разрядных архитектурах.)
  2. Реализация специфична для JVM и не является обязательным требованием.Я использую JVM от Sun, и проблем нет, но YMMV.

Кирк Пеппердайн (довольно известный гуру производительности Java) работает над веб-сайтом www.JavaPerformanceTuning.com, на котором есть еще несколько деталей MBB: Советы по производительности NIO

Если вы обращаетесь к файлам в случайная мода (читайте здесь, пропускайте, пишите там, возвращайтесь назад) тогда у вас проблема ;-)

Но если вы пишете только большие файлы, вам следует серьезно рассмотрите возможность использования потоков. java.io.FileOutputStream может использоваться непосредственно для записи файла байт за байтом или быть обернут в любой другой поток (т. е. DataOutputStream, ObjectOutputStream) для удобства написания значений с плавающей точкой, целых чисел, строк или даже сериализуемых объектов.Аналогичные классы существуют для чтения файлов.

Потоки предлагают вам удобство манипулирования сколь угодно большие файлы в (почти) сколь угодно малой памяти.В подавляющем большинстве случаев они являются предпочтительным способом доступа к файловой системе.

Используя Перенос из метод должен помочь в этом, предполагая, что вы пишете на канал постепенно, а не все сразу, как также указывают предыдущие ответы.

Это может зависеть от конкретного поставщика и версии JDK.

В некоторых JVM Sun обнаружена ошибка в GC.Нехватка прямой памяти не приведет к запуску GC в основной куче, но прямая память заблокирована мусорными байт-буферами в основной куче.Если основная куча в основном пуста, то многие из них не будут собраны в течение длительного времени.

Это может обжечь вас, даже если вы не используете прямые буферы самостоятельно, потому что JVM может создавать прямые буферы от вашего имени.Например, запись непрямого ByteBuffer в SocketChannel создает прямой буфер под обложками для использования для фактической операции ввода-вывода.

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

Предыдущие два ответа кажутся довольно разумными.Что касается того, будет ли работать переключатель командной строки, это зависит от того, насколько быстро использование вашей памяти достигнет предела.Если у вас недостаточно оперативной и виртуальной памяти, чтобы увеличить объем доступной памяти хотя бы втрое, вам нужно будет воспользоваться одним из приведенных альтернативных предложений.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top