Приложение Java тихо умирает, почему?

У меня есть java-приложение, которое загадочным образом умирает без каких-либо исключений в журналах. Я запускаю его в фоновом режиме через скрипт bash, который оборачивает nohup, как показано ниже:

nohup java -Xms6g -Xmx6g -jar myapp.jar 2>> stderr.txt >> /dev/null & echo $! > /tmp/myapp-pid

Java-приложение довольно интенсивно использует память, поэтому было настроено с 6 ГБ пространства кучи (работает на 64-битной JVM). Он работает нормально около 8 часов, а затем молча умирает. Никаких исключений в логах, ничего.

Из основного метода приложение входит в бесконечный цикл while, опрашивает AWS SQS на наличие сообщений и обрабатывает их. Все это завернуто в try-catch, и я регистрирую его. Приложение, похоже, завершает работу после завершения цикла while, поскольку оно регистрирует последнюю строку. например Приложение всегда будет заканчиваться «Успешно обработано».

while(true) {
    try {
        // Logic to poll SQS and process the message
    } catch (MyCustomException e) {
        // Write to SQS dead letter queue (was throwing at this point)
        // Delete message from original SQS
    } catch (Throwable e) {
        LOG.error(...);
    } finally { 
        LOG.info("Processing time was...");
    }
}

Я не уверен, с чего начать, так как я думал, что это что-то запишет. Может ли кто-нибудь предоставить некоторые указатели или, возможно, некоторые параметры JVM для настройки, чтобы я мог начать расследование?

Мне интересно, могут ли вещи вне кода вызывать ошибку. Например, сбой JVM?

Обновление Похоже, это действительно была ошибка программирования. Я не думал, что это вызывает проблему, поэтому я не добавил его в указанный выше путь кода (только что добавил его сейчас), но у меня было другое предложение catch, перехватывающее пользовательское исключение, которое я создал. В этом улове я пытался переместить сообщение SQS в очередь недоставленных сообщений, но не имел на это разрешения и, таким образом, бросал внутри улов, который я не обрабатывал.

Спасибо всем тем, кто помог предположить, что могло пойти не так!


person n00b    schedule 03.11.2015    source источник
comment
Ваш регистратор настроен на регистрацию уровня ERROR, а не только INFO?   -  person tbsalling    schedule 03.11.2015
comment
Два вопроса: у вас есть лог, где именно начинается время? Любая другая закономерность, кроме 8 часов, которые вы упомянули?   -  person skw    schedule 03.11.2015
comment
Судя по структуре вашего цикла, я предполагаю, что у вас есть по крайней мере одна команда break; где-то внутри цикла... В этом случае используйте редактор для поиска и замены ваших команд break; чем-то вроде System.out.println("Breakng out of loop!");break;, чтобы подтвердите, выходите ли вы из цикла через один из этих разрывов или нет; и если да, приступайте к расследованию того, какой перерыв срабатывает неправильно и почему. --- Или добавьте точки останова в каждую команду break; и используйте профилировщик для их отладки.   -  person XenoRo    schedule 03.11.2015
comment
@tbsalling - регистрируются ОШИБКИ, но не будет ли уровень ИНФОРМАЦИИ также включать ОШИБКИ?   -  person n00b    schedule 03.11.2015
comment
@skw - в начале пока нет журнала, но он регистрируется, когда опрашивает SQS, чего он не делает. 8 часов - приблизительный ориентир, это не всегда 8 часов, но через долгое время он умрет.   -  person n00b    schedule 03.11.2015
comment
@TheLima - в цикле while нет разрывов или возвратов.   -  person n00b    schedule 03.11.2015
comment
Итак, вы хотите получить сообщение об ошибке? Потому что иначе это сделает бесконечный цикл без условий выхода...   -  person XenoRo    schedule 03.11.2015
comment
почему вы отбрасываете вывод stdout на dev null? Запишите его в файл. И вам, возможно, следует создать дамп памяти.   -  person Marged    schedule 03.11.2015
comment
@Marged - возможно, я ошибаюсь, но я думал, что отбрасываю вывод nohup на dev null. Приложение использует logback для вывода в каталог журнала, который оно делает. Без ›› /dev/null я бы получил дубликаты журналов в файле «nohup.out», а также журналы, выведенные logback.   -  person n00b    schedule 03.11.2015
comment
Я видел много ситуаций, когда файл журнала не обновлялся из-за буферизации, выполняемой фреймворком ведения журнала. Поэтому, пока вы ищете ошибку, лучше иметь слишком много журналов, а не неполные ;-) Вы можете настроить это позже, когда ваша ошибка будет исправлена. И посмотрите на -XX:ErrorFile и -XX:HeapDumpPath   -  person Marged    schedule 03.11.2015


Ответы (2)


Без дополнительного кода трудно сказать, что на самом деле происходит. Но по определению finally он выполняется всегда, а значит, и в случае сбоя. Возможно, вам просто не хватает исключения, которое написано перед ним. Попробуйте переместить вызов finally внутрь блока try.

while(true) {
    try {
        // Logic to poll SQS and process the message
        LOG.info("Successfully processed");
    } catch (Throwable e) {
        //As mentioned in the comments try for debugging to log on info level here as well.
        // Maybe error level is disabled (although this should be 
        //very unlikely since error normally is written too when info is written.
        LOG.info(...);
    } finally { 
        //Clean up.
    }
}

Это две идеи, которые могут помочь вам в дальнейшем изучении вашей проблемы.

person Denis Lukenich    schedule 03.11.2015
comment
Извините, запись ввела в заблуждение. На самом деле я не регистрирую сообщение об успехе в файле finally. Я записываю время обработки. Я получаю журналы уровня INFO и ERROR, так что все в порядке. - person n00b; 03.11.2015

В вашей системе не заканчивается память? Попробуйте запустить приложение из скрипта-обертки, записав код выхода - echo $! >&2 .

Также запуск dmesg может сказать вам, выбрал ли oom killer ваше приложение в качестве жертвы.

person Zbynek Vyskovsky - kvr000    schedule 03.11.2015