Как проанализировать дамп потока java?

Я пытаюсь понять больше о java, особенно об управлении памятью и потоках. По этой причине я недавно обнаружил интерес к просмотру дампов потоков.

вот несколько строк, взятых из веб-приложения с помощью VisualVM, встроенного инструмента для java:

"Finalizer" daemon prio=8 tid=0x02b3d000 nid=0x898 in Object.wait() [0x02d0f000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x27ef0288> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
    - locked <0x27ef0288> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

   Locked ownable synchronizers:
    - None

"Reference Handler" daemon prio=10 tid=0x02b3b800 nid=0x494 in Object.wait() [0x02cbf000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x27ef0310> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:485)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
    - locked <0x27ef0310> (a java.lang.ref.Reference$Lock)

сначала у меня есть вопросы о некоторых именах переменных:

  • что означает tid и nid?
  • что такое фигура в квадратных скобках после Объект.ждать?

затем для самой трассировки стека:

  • что это значит ждем (ява.ленг....) и какое число в
  • что это значит заблокирован (ява.ленг....) тот же вопрос, что в

Я думал, что слово locked было связано каким-то образом с условием ожидания, однако я ошибался. На самом деле, я интересно, почему locked повторяется три раза, но поток находится в состоянии runnable, как видно из того же дампа:

"Thread-0" prio=6 tid=0x02ee3800 nid=0xc1c runnable [0x03eaf000]
   java.lang.Thread.State: RUNNABLE
    at java.io.FileInputStream.readBytes(Native Method)
    at java.io.FileInputStream.read(FileInputStream.java:199)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
    - locked <0x23963378> (a java.io.BufferedInputStream)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
    - locked <0x23968450> (a java.io.InputStreamReader)
    at java.io.InputStreamReader.read(InputStreamReader.java:167)
    at java.io.BufferedReader.fill(BufferedReader.java:136)
    at java.io.BufferedReader.readLine(BufferedReader.java:299)
    - locked <0x23968450> (a java.io.InputStreamReader)
    at java.io.BufferedReader.readLine(BufferedReader.java:362)
    at org.codehaus.plexus.util.cli.StreamPumper.run(StreamPumper.java:145)

тогда, наконец, это было самое худшее из них:

"CompilerThread0" daemon prio=10 tid=0x02b81000 nid=0x698 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

этот поток находится в работоспособном состоянии, но он ждет при условии. Какое условие и что такое 0x00000?

почему трассировка стека настолько коротка без каких-либо доказательств класса thread?

Если бы вы могли ответить на все мои вопросы, я был бы очень благодарный.

спасибо

3 ответов


TID-это идентификатор thead, а NID -: идентификатор собственного потока. Этот ID сильно зависит от платформы. Это NID в дампах потоков jstack. В Windows это просто идентификатор потока уровня ОС в процессе. В Linux и Solaris это PID потока (который, в свою очередь, является легким процессом). В Mac OS X это, как говорят, собственное значение pthread_t.

перейдите по этой ссылке: Java-уровня потока, ID: для определения и дальнейшего объяснения этих двух терминов.

на сайте IBM я нашел эту ссылку: как интерпретировать дамп потока. это охватывает это более подробно:

это объясняет, что означает ожидание: Блокировка запрещает доступ к общему ресурсу нескольким сущностям. Каждый объект в Java имеет соответствующий замок (полученные с помощью синхронизированного блока или метода). В случае JVM потоки конкурируют за различные ресурсы в JVM и блокируют объекты Java.

затем он описывает монитор как специальный вид механизма блокировки, который используется в JVM для обеспечения гибкой синхронизации между потоками. Для целей этого раздела прочитайте термины monitor и lock взаимозаменяемо.

и дальше:

чтобы избежать наличия монитора на каждом объекте, JVM обычно использует флаг в блоке класса или метода, чтобы указать, что элемент заблокирован. Большую часть времени часть кода будет проходить через какой-то заблокированный раздел без споров. Поэтому флага guardian достаточно для защиты этого фрагмента кода. Это называется плоский монитор. Однако, если другой поток хочет получить доступ к некоторому заблокированному коду, произошло подлинное разногласие. Теперь JVM должен создать (или раздуть) объект monitor для удержания второго потока и организовать механизм сигнализации для координации доступа к разделу кода. Этот монитор теперь называется надутым монитором.

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

"Thread-1" (TID: 0x9017A0, sys_thread_t:0x23EAC8, состояние: R, собственный идентификатор: 0x6E4) prio=5

*следующие 6 элементов объясняют это, поскольку я сопоставил их из примера, значения в скобках []:

  1. имя [поток-1],
  2. идентификатор [0x9017A0],
  3. адрес структуры данных JVM [0x23EAC8],
  4. текущее состояние [R],
  5. идентификатор собственного потока [0x6E4],
  6. и приоритет [5].

"wait on", похоже, является потоком демона, связанным с самим jvm, а не с потоком приложения. Когда ты войдешь ... Объект.wait ()", это означает, что поток демона," финализатор " здесь, ждет уведомления о блокировке объекта, в этом случае он показывает вам, какое уведомление он ждет: "- ожидание (java.ленг.ссылка.ReferenceQueue$Lock)"

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

финализатор поток выполняется таким образом, что сборка мусора работает для очистки ресурсов, связанных с объектом. Если я вижу это corectly, финализатор не может получить блокировку этого объекта: java.ленг.ссылка.ReferenceQueue.удалить(обнаруживаются.java: 118), потому что объект java выполняет метод, поэтому поток финализатора блокируется до тех пор, пока этот объект не будет завершен с его текущей задачей.

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

что такое фигура в квадратных скобках после объекта.ждите в свалка нитей?

это указатель в памяти на поток. Вот более подробное описание:

C. 4.1 Информация О Потоке

первая часть потока раздел показывает поток, который вызвал фатальную ошибку, следующим образом:

Current thread (0x0805ac88):  JavaThread "main" [_thread_in_native, id=21139]
                    |             |         |            |          +-- ID
                    |             |         |            +------------- state
                    |             |         +-------------------------- name
                    |             +------------------------------------ type
                    +-------------------------------------------------- pointer

указатель потока является указателем на внутреннюю структуру потока Java VM. Это, как правило, не представляет интереса, если вы не отлаживаете живой Java VM или основной файл.

это последнее описание пришло от:руководство по устранению неполадок для Java SE 6 С HotSpot VM

вот еще несколько ссылок на дампы потока:


далее к превосходному ответу @James Drinkard:

обратите внимание, что в зависимости от базовой реализации, то java.ленг.Нитка.Государство потока, который заблокирован в собственном методе, можно сообщить как RUNNABLE, где A thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.

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

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


попробуйте http://fastthread.io

этого достаточно прочертовский для многих случаев.