Как отследить java-программу?

25

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

В прошлом, до появления java, существовали две контрмеры:

  1. Если больше ничего не помогает - RTFM ;-)
  2. Если даже 1. не помогает - отследи системные вызовы и посмотри, что происходит

Я обычно использую strace -fдля этой задачи с Linux (другие ОС имеют аналогичные инструменты трассировки). Теперь, хотя это обычно работает для любой старомодной программы, трассировка становится очень размытой при выполнении того же самого в java -процессе. Существует так много системных вызовов, которые, по-видимому, не связаны с какими-либо реальными действиями, поэтому ужасно искать в этом дампе.

Есть ли лучшие способы сделать это (если исходный код недоступен)?

Nils
источник

Ответы:

16

Как упоминал ckhan, jstackэто здорово, потому что он дает полную трассировку стека всех активных потоков в JVM. То же самое можно получить на stderr JVM с помощью SIGQUIT.

Еще один полезный инструмент, jmapкоторый может получить дамп кучи из процесса JVM, используя PID процесса:

jmap -dump:file=/tmp/heap.hprof $PID

Этот дамп кучи может быть загружен с помощью таких инструментов, как visualvm(который теперь является частью стандартной установки Oracle java sdk с именем jvisualvm). Кроме того, VisualVM может подключаться к работающей JVM и отображать информацию о JVM, в том числе отображать графики внутреннего использования ЦП, количества потоков и использования кучи - отлично подходит для отслеживания утечек.

Другой инструмент, jstatможет собирать статистику сбора мусора для JVM за период времени, очень похожий на vmstat при запуске с числовым аргументом (например vmstat 3).

Наконец, можно использовать Java-агент для добавления инструментария во все методы всех объектов во время загрузки. Библиотека javassistможет помочь сделать это очень легко. Таким образом, возможно добавить свою собственную трассировку. Сложнее всего было бы найти способ получать результаты трассировки только тогда, когда вы этого хотели, а не постоянно, что, вероятно, замедлило бы JVM для сканирования. Есть программа под названием, dtraceкоторая работает таким образом. Я пробовал это, но не очень успешно. Обратите внимание, что агенты не могут использовать все классы, потому что те, которые необходимы для начальной загрузки JVM, загружаются до того, как агент сможет их использовать, и тогда уже слишком поздно добавлять инструменты в эти классы.

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

ясень
источник
Кстати, это потрясающий вопрос; Я надеюсь, что больше людей добавляют ответы с другими идеями. Когда я много лет просил людей, работающих с Java, отследить, они бросили на меня пустой взгляд. Возможно, они просто не знают удивительности strace.
пепел
10

Точно так же при отладке программ, которые не работают в системе Linux, вы можете использовать аналогичные инструменты для отладки запуска JVM в вашей системе.

Инструмент № 1 - jvmtop

Похожий на top , вы можете использовать jvmtop, чтобы увидеть, какие классы существуют в работающих JVM в вашей системе. После установки вы вызываете это так:

$ jvmtop.sh

Его вывод аналогично оформлен в стиле инструмента top:

 JvmTop 0.8.0 alpha   amd64  8 cpus, Linux 2.6.32-27, load avg 0.12
 http://code.google.com/p/jvmtop

  PID MAIN-CLASS      HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 3370 rapperSimpleApp  165m  455m  109m  176m  0.12%  0.00% S6U37 web        21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager   11m   28m   23m  130m  0.00%  0.00% S6U37 web        31
19187 m.jvmtop.JvmTop   20m 3544m   13m  130m  0.93%  0.47% S6U37 web        20
16733 artup.Bootstrap  159m  455m  166m  304m  0.12%  0.00% S6U37 web        46

Инструмент № 2 - jvmmonitor

Другой альтернативой является использование jvmmonitor . JVM Monitor - это профилировщик Java, интегрированный с Eclipse для мониторинга использования процессора, потоков и памяти приложениями Java. Вы можете использовать его для автоматического поиска работающих JVM на локальном хосте или подключиться к удаленным JVM с помощью port @ host.

сс из jvmmonitor

Инструмент № 3 - visualvm

VisualVM , вероятно, «инструмент», к нужно обращаться при отладке проблем с JVM. Его набор функций довольно глубокий, и вы можете очень глубоко взглянуть на внутренности.

Профилировать производительность приложения или анализировать выделение памяти:

ss of visualvm # 2

Возьмите и отобразите дампы потока:

сс из visualvm # 3

Ссылки

SLM
источник
4

Посмотрим jstack. Не совсем соответствует strace, более- pstackаналог, но, по крайней мере, даст вам моментальный снимок. Могли бы связать их вместе, чтобы получить грубый след, если нужно.

Смотрите также предложения в этой статье SO: /programming/1025681/call-trace-in-java

ckhan
источник
2

Если вы используете RHEL OpenJDK (или аналогично, дело в том, что это не JDK Oracle), вы можете использовать SystemTap для этого.

Некоторые зонды включены с помощью параметров командной строки Java -XX:+DTraceMethodProbes,-XX:+DTraceAllocProbes , -XX:+DTraceMonitorProbes. Обратите внимание, что включение этих пробников существенно повлияет на производительность программы.

Вот пример сценария SystemTap:

#!/usr/bin/stap

probe hotspot.class_loaded {
    printf("%12s [???] %s\n", name, class);
}

probe hotspot.method_entry, 
      hotspot.method_return {
    printf("%12s [%3d] %s.%s\n", name, thread_id, class, method);
}

probe hotspot.thread_start, 
      hotspot.thread_stop {
    printf("%12s [%3d] %s\n", name, id, thread_name);
}

probe hotspot.monitor_contended_enter, 
      hotspot.monitor_contended_exit {
    printf("%12s [%3d] %s\n", name, thread_id, class);
}

Вы также можете использовать jstack()для получения стека Java процесса, но он будет работать только при запуске SystemTap до JVM.


Обратите внимание, что SystemTap будет отслеживать каждый метод. Он также не может получить аргументы метода. Другой вариант - использовать собственные возможности трассировки JVM, которые называются JVMTI. Одна из самых известных реализаций JVMTI - BTrace .

myaut
источник
0

Рекомендуется попробовать Jackplay , инструмент трассировки JVM, позволяющий отслеживать входы и выходы методов без изменения или повторного развертывания кода.

alfredx
источник
Вы не можете прикрепить его к работающей JVM. Кроме того - интересный инструмент
Nils