Как исправить ошибку "Требуемый размер массива превышает VM limit" в Java?

Есть ли опция журнала, позволяющая tomcat записывать плохой запрос, а просто бросать это?

SEVERE: java.lang.OutOfMemoryError: размер запрашиваемого массива превышает предел VM

(испробовал уровень журнала до значения FULL, но только захватил выше)

Это недостаточно информации для дальнейшего отладки В качестве альтернативы, если это можно устранить, выделив больше памяти, настроив следующее?

-Xms1024M -Xmx4096M -XX: MaxPermSize = 256M

Update

-Xms6G -Xmx6G -XX: MaxPermSize = 1G -XX: PermSize = 512M

(выше все работает лучше, продолжайте мониторинг)

Ответ 1

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

Ответ 2

Я подозреваю, что вы можете использовать сортировки по большому индексу. Эта одна вещь, которую я определенно знаю, может потребовать большой размер массива с Lucene. В любом случае, вы можете попробовать использовать 64-битную JVM с этими параметрами:

-Xmx6G -XX:MaxPermSize=128M -XX:+UseCompressedOops

Последняя опция уменьшит указатели на 64-разрядные метки памяти до 32-разрядных (до тех пор, пока куча не будет ниже 32 ГБ). Это обычно уменьшает накладные расходы на память примерно на 40%, поэтому это может значительно облегчить вашу память.

Обновление: Скорее всего, вам не нужен такой большой размер постоянного поколения, конечно же, не 1G. Вероятно, вы отлично справитесь с 128M, и вы получите конкретную ошибку, если перейдете к Java 6. Поскольку вы ограничены 8G на своем сервере, вы можете уйти с 7G для кучи с меньшей влажностью поколения. Будьте осторожны, чтобы не входить в swap, что может серьезно замедлить работу Java.

Я заметил, что вы не упоминали -XX:+UseCompressedOops в своем обновлении. Это может иметь огромное значение, если вы еще не пробовали. Вы могли бы сжать немного больше пространства, уменьшив размер eden, чтобы дать поколенному поколению больше места. Помимо этого, я думаю, вам просто понадобится больше памяти или меньше полей сортировки.

Ответ 3

Если вы хотите узнать, что вызывает OutOfMemory, вы можете добавить

-XX:+HeapDumpOnOutOfMemoryError 

на ваш выбор java.

В следующий раз, когда вы выйдете из памяти, вы получите файл дампа кучи, который можно проанализировать с помощью "jhat", который находится внутри jdk/lib. Jhat покажет вам, какие объекты существуют в вашей куче и сколько памяти они потребляют.

Ответ 4

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

https://plumbr.eu/outofmemoryerror/requested-array-size-exceeds-vm-limit

Какое решение?

Java.lang.OutOfMemoryError: размер запрашиваемого массива превышает лимит VM, может появиться в результате любой из следующих ситуаций:

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

Вы намеренно пытаетесь выделить массивы размером более 2 ^ 31-1, чтобы поэкспериментировать с ограничениями.

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

Во втором случае - помните, что массивы Java индексируются по int. Таким образом, вы не можете выйти за пределы 2 ^ 31-1 элементов в своих массивах при использовании стандартных структур данных внутри платформы. Фактически, в этом случае вы уже заблокированы компилятором, объявляющим "error: integer number too large" во время компиляции. Но если вы действительно работаете с действительно большими наборами данных, вам нужно переосмыслить свои варианты. Вы можете загружать данные, необходимые для работы с меньшими партиями, и по-прежнему использовать стандартные инструменты Java, или вы можете выйти за рамки стандартных утилит. Один из способов добиться этого - заглянуть в класс sun.is.Unsafe. Это позволяет вам распределять память так же, как в C.

Ответ 5

Я использую это в catalina.sh

JAVA_OPTS="-Dsolr.solr.home=/etc/tomcat6/solr -Djava.awt.headless=true -server -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC"

У меня никогда не было проблем с памятью на Tomcat/solr с небольшими документами 30M. Однако у меня были проблемы с клиентом индексации solrJ. Мне пришлось использовать -Xms8G -Xmx8G для клиента Java и добавлять документы кусками 250K документов.

Ответ 6

Недостаточно памяти! Посмотрите, есть ли массив вне границ, или зациклите системные ресурсы поглощены!


  1. java.lang.OutOfMemoryError: Пространство кучи Java В JVM доступно 98% времени для размера кучи GC и менее 2% времени для выдачи этой информации об исключении. Настройка кучи JVM - это выполнение Java-программы. Пространство памяти JVM можно использовать для развертывания настроек. JVM при запуске автоматически устанавливает значение размера кучи, начальное пространство (т.е. Xms) является физической памятью 1/64, максимальное пространство (-Xmx) - это физическая память 1/4. JVM может использоваться для обеспечения -Xmn-Xms -Xmx и другие параметры могут быть установлены.

  2. Запрашиваемый размер массива превышает ограничение виртуальной машины: это связано с тем, что применение размера массива превышает размер пространства кучи, например 256 МБ пространства кучи в массиве для подачи заявки на 512 МБ