Подробное объяснение jstack команд JVM

JVM

существуетДемонстрация использования команды JVMВ этой статье демонстрируется использование некоторых команд jvm.Эта статья посвящена некоторым подробным объяснениям jstack.

эффект

jstack в основном используется для создания моментального снимка потока текущего момента виртуальной машины Java. Моментальный снимок потока — это набор стеков методов, которые выполняются каждым потоком в текущей виртуальной машине Java. Основная цель создания снимка потока — определить причину длительных пауз в потоках, таких как взаимоблокировки между потоками. , бесконечные циклы, запросы на внешние ресурсы, время ожидания и так далее. Когда поток приостановлен, вы можете просмотреть стек вызовов каждого потока через jstack и узнать, что не отвечающий поток делает в фоновом режиме или какие ресурсы он ожидает. jstack очень полезен, если запущенная в данный момент Java-программа находится в состоянии зависания.

использовать

первый взгляд на помощь

~ ᐅ jstack-помощь

Usage:

    jstack [-l] <pid>

        (to connect to running process)

    jstack -F [-m] [-l] <pid>

        (to connect to a hung process)

    jstack [-m] [-l] <executable> <core>

        (to connect to a core file)

    jstack [-m] [-l] [server_id@]<remote server IP or hostname>

        (to connect to a remote debug server)

Options:

    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)

    -m  to print both java and native frames (mixed mode)

    -l  long listing. Prints additional information about locks

    -h or -help to print this help message

Объясните параметры

-F: принудительно выводит стек потока, когда на обычный запрос вывода нет ответа.

-l: В дополнение к стеку будет напечатана дополнительная информация о блокировке.При возникновении взаимоблокировки вы можете использовать jstack -l pid для наблюдения за состоянием удержания блокировки.

-m: если вызывается собственный метод, может отображаться стек C/C++.

Пример

~ ᐅ jstack -F 86200

~ ᐅ jstack -l 86200

~ ᐅ jstack -m 86200

Эффект

~ ᐅ jstack -l 86200

2018-06-27 09:06:27

Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.92-b14 mixed mode):

"Attach Listener" #22 daemon prio=9 os_prio=31 tid=0x00007f93b9865000 nid=0xd07 waiting on condition [0x0000000000000000]

   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:

- None

"DestroyJavaVM" #21 prio=5 os_prio=31 tid=0x00007f93b996b800 nid=0x1803 waiting on condition [0x0000000000000000]

   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:

- None

"Buiest thread" #20 prio=5 os_prio=31 tid=0x00007f93b8138800 nid=0xa203 runnable [0x0000700004903000]

   java.lang.Thread.State: RUNNABLE

at com.mmall.practice.example.jvm.SearchBusiestCPU$2.run(SearchBusiestCPU.java:176)

   Locked ownable synchronizers:

- None

. . . Некоторые детали опущены. . .

"VM Thread" os_prio=31 tid=0x00007f93b9842000 nid=0x2d03 runnable

"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007f93b980d000 nid=0x1d07 runnable

"GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007f93b980d800 nid=0x1f03 runnable

"GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007f93b980e800 nid=0x2a03 runnable

"GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007f93b980f000 nid=0x5403 runnable

"VM Periodic Task Thread" os_prio=31 tid=0x00007f93b8aea000 nid=0x3b03 waiting on condition

JNI global references: 62

Описание анализа

Если вы хотите анализировать потоки с помощью jstack, вы должны сначала узнать состояние потока, которое вы можете увидеть, когда команда jstack просматривает информацию о стеке потока. Первый взгляд на концепцию монитора

Монитор — это основное средство для достижения взаимного исключения и взаимодействия между потоками в Java, его можно рассматривать как объектную или классовую блокировку. Каждый объект имеет и только один монитор. На приведенной выше диаграмме описывается взаимосвязь между потоком и монитором, а также диаграмма перехода состояний потока.

Область входа (Entrt Set): указывает, что поток запрашивает блокировку объекта через синхронизацию. Если объект не заблокирован, введите владельца, в противном случае подождите в зоне входа. Как только блокировка объекта снимается другими потоками, он сразу же участвует в соревновании.

Владелец: указывает, что поток успешно конкурирует за блокировку объекта.

Область ожидания (набор ожидания): указывает, что поток снимает блокировку объекта с помощью метода ожидания объекта и ожидает пробуждения в области ожидания.

Как видно из рисунка, Монитор может принадлежать только одному потоку в определенное время.Этот поток является «Активным потоком», а другие потоки — «Ожидающими потоками», которые находятся в двух очередях «Набор записей» и «Ожидание в режиме ожидания». Состояние потока, ожидающее в «Entry Set», — «Ожидание записи монитора», а состояние потока, ожидающее в «Wait Set», — «in Object.wait()». Сначала посмотрите на потоки в «наборе входов». Мы называем участок кода, защищенный синхронизацией, критическим разделом. Когда поток подает заявку на вход в критическую секцию, он входит Очередь «Набор входа».

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

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

Runnable обычно означает, что поток находится в состоянии выполнения, поток занимает ресурсы, обрабатывает запрос, может передавать SQL в базу данных для выполнения, может работать с определенным файлом, может преобразовывать типы данных и т. д.

Ожидание условия (фокус), ожидание ресурса или ожидание выполнения условия. Конкретные причины необходимо анализировать в сочетании с фактическим стеком.

  • Одна ситуация заключается в том, что сеть очень загружена, почти полностью использует пропускную способность, и все еще есть много данных, ожидающих чтения и записи сетью;

  • Другая ситуация может заключаться в том, что сеть простаивает, но из-за таких проблем, как маршрутизация, пакеты не могут нормально поступать.

  • Если информация о стеке явно представляет собой код приложения, это доказывает, что поток ожидает ресурса. Как правило, когда считывается большое количество ресурсов и ресурс использует блокировку ресурса, поток переходит в состояние ожидания и ожидает чтения ресурса.

  • Или он ожидает выполнения других потоков и т. д.

  • Если обнаруживается, что большое количество потоков находится в состоянии ожидания, из стека потоков они ожидают чтения и записи в сети, что может быть признаком узкого места в сети. Поток не может быть выполнен из-за перегрузки сети.

  • Другая распространенная ситуация, когда возникает условие ожидания, заключается в том, что поток находится в спящем режиме и будет разбужен, когда время ожидания истечет.

Ожидание входа в монитор (фокус), ожидание входа в критическую секцию

Object.wait() или TIMED_WAITING, указывая на то, что он вызвал метод java.lang.Object.wait() после получения монитора. Каждый монитор может принадлежать только одному потоку в определенное время, который является «активным потоком», а другие потоки являются «ожидающими потоками», ожидающими в двух очередях «Entry Set» и «Wait Set» соответственно. Состояние потока, ожидающее в «Наборе записей», — «Ожидание записи монитора», а в «Ожидание». Состояние потока, ожидающего в Set, — это «in Object.wait()». Когда поток получает монитор, если он обнаруживает, что условия для продолжения выполнения потока не выполняются, он вызывает метод wait() функции объекта (обычно синхронизируемого объекта), отказались от Монитора и вошли в очередь «Ожидание установки».

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

  • java.lang.Thread.State: TIMED_WAITING(на мониторе объекта);

  • java.lang.Thread.State: WAITING(на мониторе объекта);

Заблокировано (фокус на), блокировка потока, означает, что во время выполнения текущего потока требуемые ресурсы ожидаются в течение длительного времени, но не получены, и помечаются как заблокированные диспетчером потоков контейнера, что может пониматься как поток, ожидающий тайм-аута ресурса

Демонстрация тупиковой ситуации

Сначала подготовьте код взаимоблокировки

@Slf4jpublic class DeadLock implements Runnable {    public int flag = 1;    //静态对象是类的所有对象共享的    private static Object o1 = new Object(), o2 = new Object();    @Override    public void run() {        log.info("flag:{}", flag);        if (flag == 1) {            synchronized (o1) {                try {                    Thread.sleep(500);                } catch (Exception e) {                    e.printStackTrace();                }                synchronized (o2) {                    log.info("1");                }            }        }        if (flag == 0) {            synchronized (o2) {                try {                    Thread.sleep(500);                } catch (Exception e) {                    e.printStackTrace();                }                synchronized (o1) {                    log.info("0");                }            }        }    }    public static void main(String[] args) {        DeadLock td1 = new DeadLock();        DeadLock td2 = new DeadLock();        td1.flag = 1;        td2.flag = 0;        //td1,td2都处于可执行状态,但JVM线程调度先执行哪个线程是不确定的。        //td2的run()可能在td1的run()之前运行        new Thread(td1).start();        new Thread(td2).start();    }}

Результаты приведены ниже:

14:47:19.351 [Thread-1] INFO com.mmall.concurrency.example.deadLock.DeadLock - flag:0

14:47:19.351 [Thread-0] INFO com.mmall.concurrency.example.deadLock.DeadLock - flag:1

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

Используйте команду jstack для просмотра информации о стеке

~ ᐅ jps

93893 Launcher

94055 Jps

93894 DeadLock

34413

~ ᐅ jstack -l 93894

2018-06-28 14:48:26

Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.92-b14 mixed mode):

"Attach Listener" #13 daemon prio=9 os_prio=31 tid=0x00007ff14c101800 nid=0x1307 waiting on condition [0x0000000000000000]

   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:

- None

"DestroyJavaVM" #12 prio=5 os_prio=31 tid=0x00007ff14c0fe000 nid=0x1703 waiting on condition [0x0000000000000000]

   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:

- None

"Thread-1" #11 prio=5 os_prio=31 tid=0x00007ff14ca77000 nid=0x3d03 waiting for monitor entry [0x000070000c45c000]

   java.lang.Thread.State: BLOCKED (on object monitor)

at com.mmall.concurrency.example.deadLock.DeadLock.run(DeadLock.java:43)

- waiting to lock <0x000000076b5115c0> (a java.lang.Object)

- locked <0x000000076b5115d0> (a java.lang.Object)

at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:

- None

"Thread-0" #10 prio=5 os_prio=31 tid=0x00007ff14ca4b000 nid=0x3c03 waiting for monitor entry [0x000070000c359000]

   java.lang.Thread.State: BLOCKED (on object monitor)

at com.mmall.concurrency.example.deadLock.DeadLock.run(DeadLock.java:31)

- waiting to lock <0x000000076b5115d0> (a java.lang.Object)

- locked <0x000000076b5115c0> (a java.lang.Object)

at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:

- None

. . .此处省略部分无用的thread堆栈信息。 . .

"VM Thread" os_prio=31 tid=0x00007ff14b82b000 nid=0x2d03 runnable

"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007ff14c012800 nid=0x2107 runnable

"GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007ff14c013000 nid=0x2003 runnable

"GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007ff14c816000 nid=0x2a03 runnable

"GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007ff14c816800 nid=0x5403 runnable

"VM Periodic Task Thread" os_prio=31 tid=0x00007ff14ca0b000 nid=0x3a03 waiting on condition

JNI global references: 42

Found one Java-level deadlock:

=============================

"Thread-1":

  waiting to lock monitor 0x00007ff14b0195c8 (object 0x000000076b5115c0, a java.lang.Object),

  which is held by "Thread-0"

"Thread-0":

  waiting to lock monitor 0x00007ff14b0174c8 (object 0x000000076b5115d0, a java.lang.Object),

  which is held by "Thread-1"

Java stack information for the threads listed above:

===================================================

"Thread-1":

at com.mmall.concurrency.example.deadLock.DeadLock.run(DeadLock.java:43)

- waiting to lock <0x000000076b5115c0> (a java.lang.Object)

- locked <0x000000076b5115d0> (a java.lang.Object)

at java.lang.Thread.run(Thread.java:745)

"Thread-0":

at com.mmall.concurrency.example.deadLock.DeadLock.run(DeadLock.java:31)

- waiting to lock <0x000000076b5115d0> (a java.lang.Object)

- locked <0x000000076b5115c0> (a java.lang.Object)

at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

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

Уведомление

1. Способ создания и формат файла дампа потока для разных виртуальных машин JAVA могут различаться, разные версии JVM имеют разную информацию о дампе.

2. В реальной эксплуатации информации одного дампа часто бывает недостаточно для подтверждения проблемы. Рекомендуется формировать дамп информации 2-3 раза, если каждый дамп указывает на одну и ту же проблему, можно определить типичность проблемы.

Рекомендуем другие статьи

Подготовка и проработка параллельных вопросов в интервью

Пользовательские аннотации завершают резку базы данных

Легко поддерживается несколько источников данных

Реформирование процесса управления полномочиями на фоне операций электронной коммерции

Универсальный дизайн разрешения данных

Кратко о построении системы мониторинга и сигнализации для бизнеса с нуля

Некоторые сведения об использовании журнала для записи журналов в проектах Java

Практика Redis при расчете графика K-line с разделением времени на складе

Параллельное использование Fork/Join Framework и замечания

Параллельное программирование на Java и решения с высокой степенью параллелизма:

https://coding.imooc.com/class/195.html

Управление правами на уровне предприятия при разработке Java система:

https://coding.imooc.com/class/149.html

Если вам нравятся связанные технические статьи, не забудьте подписаться на меня~