Ошибка JVM OutOfMemory “смертельная спираль” (не утечка памяти)

Мы недавно перемещали много приложений от выполнения под RedHat linux JDK1.6.0_03 к Солярису 10u8 JDK1.6.0_16 (намного более высокие машины спецификации), и мы заметили то, что, кажется, довольно насущная проблема: при определенных загрузках наши JVMs вовлекают себя в "Смертельную Спираль" и в конечном счете выходят из памяти. Вещи отметить:

  • это не случай утечки памяти. Это приложения, которые работали очень хорошо (в одном случае больше 3 лет), и ошибки из памяти не являются бесспорными в любом случае. Иногда работа приложений, иногда они не делают
  • это не мы перемещающийся в 64-разрядный VM - мы все еще выполняем 32 бита
  • В одном случае, с помощью последнего сборщика "мусора" G1 на 1.6.0_18, кажется, решил проблему. В другом, пятясь к 1.6.0_03 работал
  • Иногда наши приложения падают с HotSpot SIGSEGV ошибки
  • Это влияет на приложения, записанные в Java, а также Scala

Наиболее важный момент - это: поведение проявляется в тех приложениях, которые внезапно получают наводнение данных (обычно через TCP). Это - как будто VM решает продолжать добавлять больше данных (возможно прогрессирующий он до TG) вместо того, чтобы выполнить GC на "newspace", пока это не понимает, что должно сделать полный GC и затем, несмотря на практически все в VM быть мусором, это так или иначе решает не собрать его!

Это звучит сумасшедшим, но я просто не вижу то, что еще это. Как еще может Вы объяснять приложение, за которое одна минута запинается и падает с макс. "кучей" 1 ГБ, и следующее работает просто великолепно (никогда не идущий о 256M, когда приложение делает точно то же самое),

Таким образом, мои вопросы:

  1. Кто-либо еще наблюдал этот вид поведения?
  2. у кого-либо есть какие-либо предложения относительно того, как я мог бы отладить саму JVM (в противоположность моему приложению)? Как я доказываю, что это - проблема VM?
  3. Есть ли какие-либо форумы VM-специалиста там, где я могу спросить авторов VM (предполагающий, что они не находятся на ТАК)? (У нас нет контракта на поддержку),
  4. Если это - ошибка в последних версиях VM, каким образом никто еще не заметил его?
19
задан oxbow_lakes 19 February 2010 в 16:34
поделиться

6 ответов

В Oracle

WITH
START_DATE AS
(
    SELECT TO_CHAR(TO_DATE('JANUARY 5 2010','MONTH DD YYYY'),'J') 
    JULIAN FROM DUAL
),
END_DATE AS
(
    SELECT TO_CHAR(TO_DATE('JANUARY 30 2010','MONTH DD YYYY'),'J') 
    JULIAN FROM DUAL
),
DAYS AS
(
    SELECT END_DATE.JULIAN - START_DATE.JULIAN DIFF
    FROM START_DATE, END_DATE
)
SELECT  TO_CHAR(TO_DATE(N + START_DATE.JULIAN, 'J'), 'MONTH DD YYYY') 
        DESIRED_DATES
FROM 
START_DATE,
(
    SELECT LEVEL N 
    FROM DUAL, DAYS
    CONNECT BY LEVEL < DAYS.DIFF
)
-121--4648280-

я бы предположил, что нормализованный способ будет более быстрым как для операций INSERT, так и для операций SELECT, хотя бы потому, что именно для этого будет оптимизирована любая RDBMS. Часть «Объем задействованных данных» тоже может быть проблемой, но более разрешимой - как долго вам нужны эти данные сразу на руках, можете ли вы архивировать их через день, пару недель или 3 месяца и т.д.? SQL Server может справиться с большим количеством проблем.

Эти данные о событии будут постоянно передаваться в потоковом режиме, поэтому время вставки так же важно, как время запроса.

Вариант 3: Если у вас действительно есть много данных, постоянно передаваемых в потоковом режиме - создайте отдельную очередь в общей памяти, внутрипроцессном sqlite, отдельной таблице БД или даже на собственном сервере, чтобы сохранить входящее необработанное событие и атрибуты, а другой процесс (запланированная задача, служба Windows и т. д.) проанализируйте эту очередь в любом предпочтительном формате, настроенном для быстрых SMTP. Оптимальный ввод, оптимальный вывод, готовность к масштабированию в любом направлении, все довольны.

-121--4349322-

Интересная проблема. Звучит так, будто один из сборщиков мусора плохо работает на вашей конкретной ситуации.

Пытались ли вы изменить используемый сборщик мусора? Существует МНОГО вариантов GC, и выяснение, какие из них оптимальны, кажется, немного черного искусства, но мне интересно, сработает ли для вас базовое изменение.

Я знаю, что существует «сервер» GC, который имеет тенденцию работать намного лучше, чем по умолчанию. Вы используете этот?

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

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

2
ответ дан 30 November 2019 в 05:18
поделиться

У меня была такая же проблема на машинах Solaris, и я решил ее, уменьшив максимальный размер JVM. 32-битная реализация Solaris, очевидно, нуждается в некотором дополнительном пространстве сверх того, что вы выделяете для JVM при выполнении сборки мусора. Так, например, при -Xmx3580M я получу описанные вами ошибки, но при -Xmx3072M все будет нормально.

2
ответ дан 30 November 2019 в 05:18
поделиться

Какого рода OutOfMemoryError вы получаете? Исчерпано ли место в куче или проблема связана с каким-либо другим пулом памяти (Ошибка обычно имеет сообщение с более подробной информацией о ее причине).

Если куча исчерпана и проблема может быть воспроизведена (похоже, что может), я бы прежде всего настроил виртуальную машину на создание дампа кучи при OutOfMemoryErrors. Затем вы можете проанализировать кучу и убедиться, что она не заполнена объектами, которые все еще доступны через неожиданные ссылки.

Конечно, не исключено, что вы столкнулись с ошибкой VM, но если ваше приложение полагается на специфическое поведение реализации в 1.6.0_03, оно может по тем или иным причинам оказаться загрузчиком памяти при работе на 1.6.0_16. Такие проблемы также могут возникнуть, если вы используете какой-либо серверный контейнер для своего приложения. Некоторые разработчики, очевидно, не умеют читать документацию, но склонны наблюдать за поведением API и делать собственные выводы о том, как что-то должно работать. Это, конечно, не всегда правильно, и я сталкивался с подобными проблемами как с Tomcat, так и с JBoss (оба продукта, по крайней мере, раньше работали только с определенными виртуальными машинами).

1
ответ дан 30 November 2019 в 05:18
поделиться

Также убедитесь, что это не аппаратная ошибка (попробуйте запустить MemTest86 или что-то подобное на сервере)

.
1
ответ дан 30 November 2019 в 05:18
поделиться

С какими именно ошибками SIGSEV вы сталкиваетесь?

Если вы используете 32-битную VM, это может быть то, что я описал здесь: http://janvanbesien.blogspot.com/2009/08/mysterious-jvm-crashes-explained.html

1
ответ дан 30 November 2019 в 05:18
поделиться
  1. Да, я наблюдал такое поведение раньше, и обычно после бесчисленных часов подстройки параметров JVM оно начинает работать.
  2. Сборка мусора, особенно в многопоточных ситуациях, является недетерминированной. Определить ошибку в недетерминированном коде может быть непросто. Но вы можете попробовать DTrace, если вы используете Solaris, и есть много вариантов JVM для пиринга в HotSpot.
  3. Зайдите в Scala IRC и посмотрите, не болтается ли там Исмаэль Джума (ijuma). Он уже помогал мне раньше, но я думаю, что за настоящую глубокую помощь нужно платить.
  4. Я думаю, большинство людей, занимающихся подобными вещами, признают, что им нужно быть экспертами по настройке JVM, иметь их в штате или нанять консультанта. Есть люди, которые специализируются на настройке JVM.

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

2
ответ дан 30 November 2019 в 05:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: