Сбой виртуальной машины Java 6 (обновление 25): недостаточно памяти

Обновленную информацию по этому вопросу см. ниже.

Я испытываю (воспроизводимый, по крайней мере, для меня) JVM сбой (не OutOfMemoryError) (аварийное завершение приложения - eclipse 3.6.2). Однако, глядя на журнал сбоев, я задаюсь вопросом:

#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (malloc) failed to allocate 65544 bytes for Chunk::new
# Possible reasons:
#   The system is out of physical RAM or swap space
#   In 32-bit mode, the process size limit was hit
# Possible solutions:
#   Reduce memory load on the system
#   Increase physical memory or swap space
#   Check if swap backing store is full
#   Use 64 bit Java on a 64 bit OS
#   Decrease Java heap size (-Xmx/-Xms)
#   Decrease number of Java threads
#   Decrease Java thread stack sizes (-Xss)
#   Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.

Current thread (0x531d6000):  JavaThread "C2 CompilerThread1" daemon 
[_thread_in_native, id=7812, stack(0x53af0000,0x53bf0000)]

Stack: [0x53af0000,0x53bf0000],  sp=0x53bee860,  free space=1018k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [jvm.dll+0x1484aa]
V  [jvm.dll+0x1434fc]
V  [jvm.dll+0x5e6fc]
V  [jvm.dll+0x5e993]
V  [jvm.dll+0x27a571]
V  [jvm.dll+0x258672]
V  [jvm.dll+0x25ed93]
V  [jvm.dll+0x260072]
V  [jvm.dll+0x24e59a]
V  [jvm.dll+0x47edd]
V  [jvm.dll+0x48a6f]
V  [jvm.dll+0x12dcd4]
V  [jvm.dll+0x155a0c]
C  [MSVCR71.dll+0xb381]
C  [kernel32.dll+0xb729]

Я использую 32-разрядную версию Windows XP SP3. У меня 4 ГБ ОЗУ. Перед запуском приложения у меня было 2 ГБ свободного места в соответствии с диспетчером задач (+ 1 ГБ системного кеша, который также мог быть освобожден). У меня определенно достаточно свободной оперативной памяти.

С самого начала до сбоя я регистрировал статистику памяти JVM с помощью visualvm и jconsole. Статистику потребления памяти я получил до последних моментов перед сбоем.

Статистика показывает следующие размеры выделенной памяти:

  • HeapSize: 751 МБ (использовалось 248 МБ)
  • Non-HeapSize (PermGen и CodeCache): 150 МБ (использовалось 95 МБ)
  • Размер областей управления памятью (Edenspace, Old-gen и т. Д.): 350 МБ
  • Размер стека потоков: 17 МБ (согласно oracle и из-за того, что работает 51 поток)

Я запускаю приложение (jre 6 update 25, server vm), используя параметры:

-XX:PermSize=128m
-XX:MaxPermSize=192m
-XX:ReservedCodeCacheSize=96m
-Xms500m
-Xmx1124m

Вопрос:

  • Почему происходит сбой JVM, когда очевидно, что на виртуальной машине и ОС достаточно памяти?
    Я думаю, что с указанными выше настройками я не могу достичь 32-разрядного лимита в 2 ГБ (1124 МБ + 192 МБ + 96 МБ + поток стеки ‹2ГБ). В любом другом случае (слишком много выделения кучи) я бы скорее ожидал OutOfMemoryError, чем сбой JVM

Кто может помочь мне разобраться в том, что здесь не так?

(Примечание: я недавно обновился до Eclipse 3.6.2 с Eclipse 3.4.2 и с Java 5 до Java 6. Я подозреваю, что существует связь между сбоями и этими изменениями, потому что я не видел их раньше)

ОБНОВЛЕНИЕ

Похоже, это ошибка JVM введен в Java 6 Update 25 и имеет какое-то отношение к новому компилятору jit. См. Также эту запись в блоге. Согласно блогу, исправление этой ошибки должно быть частью следующих обновлений Java 6. Между тем, во время сбоя у меня была трассировка нативного стека. Я обновил приведенный выше журнал сбоев.

Предлагаемый обходной путь с использованием аргумента VM -XX:-DoEscapeAnalysis работает (по крайней мере, он заметно снижает вероятность сбоя)


person MRalwasser    schedule 14.06.2011    source источник
comment
Возможно, вы установили слишком высокий максимальный размер памяти для поддержки 32-разрядного пространства. Обычно JVM обнаруживает это, но вы можете приблизиться к пределу так, как она не может обнаружить.   -  person Peter Lawrey    schedule 14.06.2011
comment
Если вы увеличите PermSize до 512m и добавите -XX:PermSize=512m, ошибка по-прежнему возникает?   -  person Buhake Sindi    schedule 14.06.2011
comment
Какая это версия Java 6? Описание похоже на этот идентификатор ошибки, за исключением дампа потока. .   -  person Vineet Reynolds    schedule 14.06.2011
comment
Затем проверьте отчет об ошибке и попробуйте обходной путь. Или используйте u23.   -  person Vineet Reynolds    schedule 14.06.2011
comment
@Vineet Согласно отчету (это дубликат, также посмотрите исходный отчет об ошибке) проблема с памятью возникает при использовании -XX:+DoEscapeAnalysis. Однако я не использую этот вариант.   -  person MRalwasser    schedule 14.06.2011
comment
Что будет больно, если вы попробуете использовать -XX:-DoEscapeAnalysis?   -  person Vineet Reynolds    schedule 14.06.2011
comment
Я думаю, что этот вариант вызывает проблему в соответствии с исходным отчетом об ошибке (который противоречит дубликату). Я думаю, что в дубликате, который вы связали, есть ошибка ввода в предложенном обходном пути Try -XX: -DoEscapeAnalysis. который скорее должен быть Попробуйте опустить -XX: -DoEscapeAnalysis. Тем не менее я попробую эту настройку.   -  person MRalwasser    schedule 14.06.2011
comment
Что ж, если ничего не помогает, перейдите к более ранней сборке Oracle JVM или даже JRockit.   -  person Vineet Reynolds    schedule 14.06.2011
comment
У меня такая же проблема в Windows 2003, даже если я обновлю JDK до 6u33-b03 x86   -  person 爱国者    schedule 18.07.2012
comment
В чем заключается ваш настоящий вопрос?   -  person Amir Afghani    schedule 21.01.2020


Ответы (4)


2 ГБ на 32-разрядной JVM в Windows неверно. https://blogs.sap.com/2019/10/07/does-32-bit-or-64-bit-jvm-matter-anymore/

Поскольку вы используете Windows-XP, вы застряли на 32-битной JVM.

Максимальный размер кучи составляет 1,5 ГБ на 32-разрядной виртуальной машине в Windows. У вас 1412 МБ для начала без потоков. Вы пытались уменьшить размер стека подкачки -Xss и пытались ли вы удалить изначально выделенный PermSize: -XX: PermSize = 128m? Похоже, это проблема затмения, а не проблема памяти как таковая.

Можете ли вы перейти на новую JVM или другую (64-битную) JVM на другом компьютере? Даже если вы ориентируетесь на Windows-XP, нет причин разрабатывать на нем, если только вы НЕ ДОЛЖНЫ. Eclipse может легко запускать, отлаживать и развертывать код на удаленных машинах.

JVM Eclipse может отличаться от JVM вещей, в которых вы работаете или с eclipse. Eclipse - это свинья памяти. Вы можете исключить ненужные плагины eclipse, чтобы использовать меньше памяти eclipse, он поставляется с вещами из коробки, которые вам, вероятно, не нужны или не нужны.

Попробуйте обнулить ссылки (чтобы исключить циклически не собираемые объекты GC), повторно используйте выделенную память, используйте одиночные объекты и профилируйте использование памяти, чтобы исключить ненужные объекты, ссылки и выделения. Дополнительные советы:

  • Предпочитайте статическое распределение памяти, то есть выделяйте один раз для каждой виртуальной машины, а не динамически.
  • Избегайте создания временных объектов внутри функций - рассмотрите метод reset (), который позволяет повторно использовать объект.
  • Избегайте мутаций строк и мутаций автоматически упакованных типов.
person ggb667    schedule 18.02.2020

Я думаю, что @ ggb667 объяснил причину сбоя вашей JVM. 32-разрядные архитектурные ограничения Windows ограничивают доступную оперативную память для приложения Java до 1,5 ГБ 1 ... а не 2 ГБ, как вы предполагали. Кроме того, вы не включили адресное пространство, занимаемое сегментом кода исполняемого файла, разделяемыми библиотеками, собственной кучей и другими вещами.

По сути, это не ошибка JVM. Вы просто работаете с ограничениями вашего оборудования и операционной системы.

Возможное решение - поддержка PAE (расширение физического адреса) в некоторых версиях Windows. Согласно ссылке, Windows XP с PAE предоставляет пользовательским процессам до 4 ГБ доступного адресного пространства. Однако есть предостережения относительно поддержки драйверов устройств.

Другое возможное решение - уменьшить максимальный размер кучи и предпринять другие действия для уменьшения использования памяти приложением; например в Eclipse уменьшите количество открытых проектов в вашем рабочем пространстве.

См. Также: Максимальная память Java в Windows XP

1 - Различные источники по-разному говорят о фактическом лимите, но он значительно меньше 2 ГБ. Откровенно говоря, реальный лимит не имеет значения.


В идеальном мире этот вопрос больше никого не должен интересовать. В 2020 году:

  • Вы не должны использовать Windows XP. Это конец жизни с апреля 2014 года.
  • Вы не должны использовать Java 6. Срок его службы закончился с апреля 2013 года.
  • Если вы все еще используете Java 6, у вас должен быть последний общедоступный выпуск исправлений: 1.6.0_45. (Или более поздний закрытый выпуск 1.6, если у вас есть / был контракт на поддержку.)

В любом случае вы не должны запускать Eclipse в этой системе. Серьезно, вы можете получить новую 64-битную машину за несколько сотен долларов с большей памятью и т. Д., Что позволит вам запускать новейшую операционную систему и последнюю версию Java. Вы должны использовать это для запуска Eclipse.

Если вам действительно нужно заниматься Java-разработкой на старой 32-битной машине со старой версией Java (потому что вы не можете позволить себе новую машину), вам будет рекомендовано использовать простой текстовый редактор и инструменты командной строки Java 6 JDK. (и сторонний инструмент сборки Java, такой как Ant, Maven, Gradle).

Наконец, если вы все еще пытаетесь запускать / поддерживать программное обеспечение Java, которое застряло на Java 6, вам действительно следует попытаться выбраться из этой дыры. Жить тебе будет только труднее:

  • Если программное обеспечение Java 6 было разработано собственными силами или у вас есть исходный код, перенесите его.
  • Если вы зависите от проприетарного программного обеспечения, застрявшего на Java 6, поищите нового поставщика.
  • Если руководство говорит «нет», скажите им, что им, возможно, придется его выключить.

Вы / ваша организация должны были заняться этим вопросом СЕМЬ лет назад.

person Stephen C    schedule 04.07.2020

На работе наткнулся на аналогичную проблему. Мы установили -Xmx65536M для нашего приложения, но продолжали получать точно такие же ошибки. Забавно то, что ошибки возникали всегда в то время, когда наше приложение фактически выполняло довольно легкие вычисления, условно говоря, и, таким образом, далеко не приближалось к этому пределу.

Мы нашли возможное решение проблемы в Интернете: http://www.blogsoncloud.com/jsp/techSols/java-lang-OutOfMemoryError-unable-to-create-new-native-thread.jsp, и это, похоже, решило нашу проблему . После снижения -Xmx до 50G у нас не было ни одной из этих проблем.

Что же на самом деле происходит в этом деле, нам до сих пор в некоторой степени непонятно.

person jesseniem    schedule 10.07.2012

У JVM есть свои ограничения, которые остановят ее задолго до того, как она достигнет пределов физической или виртуальной памяти. Что вам нужно настроить, так это размер кучи, который соответствует еще одному из флагов -X. (Я думаю, что это что-то креативное, например -XHeapSizeLimit, но я проверю через секунду.)

Начнем:

-Xmsn Задает начальный размер пула распределения памяти в байтах. Это значение должно быть кратным 1024 и превышать 1 МБ. Добавьте букву k или K, чтобы указать килобайты, или m или M, чтобы указать мегабайты. Значение по умолчанию - 2 МБ. Примеры:

   -Xms6291456
   -Xms6144k
   -Xms6m

-Xmxn Задает максимальный размер пула распределения памяти в байтах. Это значение должно быть кратным 1024 и превышать 2 МБ. Добавьте букву k или K, чтобы указать килобайты, или m или M, чтобы указать мегабайты. Значение по умолчанию - 64 МБ. Примеры:

   -Xmx83886080
   -Xmx81920k
   -Xmx80m
person Charlie Martin    schedule 14.06.2011
comment
Вы имеете в виду -Xmx? Это то, что я здесь устанавливаю. И, как указано в сообщении, я теоретически не могу достичь этого предела, и даже если бы я бы это сделал, я бы предпочел получить OutOfMemoryError - так что это не может быть так, ИМХО. - person MRalwasser; 14.06.2011
comment
Вы не знаете, что это не может быть так, поскольку вы смотрите только на последний образец перед вылетом. Посмотрите здесь oracle.com/technetwork/java/ javase / tech / и попробуйте установить -XX: -HeapDumpOnOutOfMemoryError - person Charlie Martin; 14.06.2011
comment
Вы также захотите посмотреть на jmap oracle.com/ technetwork / articles / javase / - person Charlie Martin; 14.06.2011
comment
@Charlie Я не получаю OutOfMemoryError, поэтому вариант, который вы предлагаете, не может сработать. Я получаю сбой jvm, а это совсем другое дело. - person MRalwasser; 14.06.2011
comment
@MR Я рад, что ты знаешь, что не так. Но тогда почему вы спрашиваете? - person Charlie Martin; 14.06.2011
comment
Прошу прощения, если вы ошиблись. Я не сказал, что знаю, что случилось, но я знаю, что это не OutOfMemoryError. И когда jvm аварийно завершает работу (= основной дамп), обычные обработчики ошибок, такие как предложенные вами механизмы дампа кучи, недоступны. И, кстати, я почти уже достиг максимального размера кучи для моей ОС. - person MRalwasser; 14.06.2011