OutOfMemoryError в StringBuilder.append() даже с более чем достаточным объемом памяти

Я получаю OutOfMemoryError из java.lang.StringBuilder.append, даже когда я устанавливаю размер памяти на 32 ГБ и считываю в построитель только файл размером 500 МБ.

java.lang.OutOfMemoryError: null
    at java.base/java.lang.AbstractStringBuilder.hugeCapacity(AbstractStringBuilder.java:214) ~[na:na]
    at java.base/java.lang.AbstractStringBuilder.newCapacity(AbstractStringBuilder.java:206) ~[na:na]
    at java.base/java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:173) ~[na:na]
    at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:538) ~[na:na]
    at java.base/java.lang.StringBuilder.append(StringBuilder.java:174) ~[na:na]
    at com.github.loa.indexer.service.index.base64.Base64Encoder.encode(Base64Encoder.java:31) ~[classes/:na]

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

Albatross 30.05.2019 21:02

Мой вариант использования довольно сложный. Пытаясь передать файл в массивы байтов в кусках длиной 3072 байта, затем закодировать куски с помощью java.util.Base64, добавить результат кодирования в StringBuilder. К сожалению, StringBuilder быстро умирает. Мне нужно получить всю строку base64 в памяти, чтобы отправить ее в Elasticsearch (потоковая передача невозможна). Код доступен здесь: github.com/bottomless-archive-project/library-of-alexandria/‌​…

Lakatos Gyula 30.05.2019 21:16

Какую версию Java вы используете?

Andreas 30.05.2019 21:38

@Andreas Java 11. Я думаю, что это относится к Java 9+, но не уверен.

Lakatos Gyula 30.05.2019 22:07

Немного небрежно, что они бросают OOM. Теперь мне нужно поймать это где-то в моем коде, и я знаю, что ловить OOM довольно плохо.

Lakatos Gyula 30.05.2019 22:09
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
5
404
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это происходит потому, что массив байтов, который StringBuilder хочет выделить, потребует большего размера массива, чем разрешено JVM (более 2147483647 элементов, также известных как Integer.MAX_VALUE).

Иными словами, это ограничение Java, что размер строки не может превышать 2 ГБ, что обычно означает, что он не может превышать 1 миллиард символов (строки только для latin1 могут иметь 2 миллиарда символов в более поздних версиях Java).

Andreas 30.05.2019 21:11

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