如何分析java线程转储? [英] How to analyze a java thread dump?

查看:114
本文介绍了如何分析java线程转储?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图更多地了解java,特别是关于内存管理和线程。
因此我最近发现有兴趣查看线程转储。



以下是使用VisualVM(一种内置工具)从Web应用程序中获取的几行for java:

 Finalizer守护程序prio = 8 tid = 0x02b3d000 nid = 0x898 in Object.wait()[0x02d0f000] 
java.lang.Thread.State:WAITING(在对象监视器上)
at java.lang.Object.wait(Native Method)
- wait on< 0x27ef0288> (java.lang.ref.ReferenceQueue $ Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked< 0x27ef0288> (java.lang.ref.ReferenceQueue $ Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer $ FinalizerThread.run( Finalizer.java:159)

锁定的可拥有同步器:
- 无

参考处理程序守护程序prio = 10 tid = 0x02b3b800 nid = 0x494 in Object.wait ()[0x02cbf000]
java.lang.Thread.State:WAITING(在对象监视器上)
at java.lang.Object.wait(Native Method)
- wait on< 0x27ef0310> (java.lang.ref.Reference $ Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference $ ReferenceHandler.run(Reference。 java:116)
- 已锁定< 0x27ef0310> (一个java.lang.ref.Reference $ Lock)

首先我对一些变量名称有疑问:




  • tid和nid是什么意思?

  • Object.wait之后的平方括号中的数字是什么?



然后是堆栈跟踪自己:




  • 这是什么意思等待< .....>(一个java.lang ... 。)中的数字<...>

  • 这是什么意思已锁定< .....> (一个java.lang ....)同样的问题,< ..>
  • 中的内容


我认为锁定这个词在某种程度上与等待条件有关,但是,我错了。事实上,我想知道为什么锁定重复三次,但线程处于可运行状态,如同一个转储中所示:

 Thread-0prio = 6 tid = 0x02ee3800 nid = 0xc1c runnable [0x03eaf000] 
java.lang.Thread.State:java.io.FileInputStream.readBytes(Native Method)
$ R $ $ b在java.io.FileInputStream.read(FileInputStream.java:199)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
at java.io.BufferedInputStream.read(BufferedInputStream) .java:317)
- 已锁定< 0x23963378> (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)
- 已锁定< 0x23968450> (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> (java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at org.codehaus.plexus.util.cli.StreamPumper.run(StreamPumper.java: 145)

然后最后,这是最糟糕的:

 CompilerThread0守护程序prio = 10 tid = 0x02b81000 nid = 0x698等待条件[0x00000000] 
java.lang.Thread.State:RUNNABLE

此线程处于可运行状态,但它正在等待条件。什么条件和什么是0x00000?



为什么堆栈跟踪如此短暂而没有任何线程类的证据?



<如果你能回答我的所有问题,我将非常感激。



谢谢

解决方案

TID是thead id,NID是:本机线程ID。此ID高度依赖于平台。它是jstack线程转储中的NID。在Windows上,它只是进程中的操作系统级线程ID。在Linux和Solaris上,它是线程的PID(反过来又是一个轻量级的过程)。在Mac OS X上,它被称为本机pthread_t值。



转到此链接: Java级线程ID :有关这两个术语的定义和进一步说明。



在IBM的网站上,我找到了这个链接:如何解释线程转储。更详细地介绍了这一点:



它解释了等待的含义:
锁定阻止多个实体访问共享资源。 Java™中的每个对象都有一个关联的锁(通过使用同步块或方法获得)。对于JVM,线程在JVM中竞争各种资源并锁定Java对象。



然后它将监视器描述为一种特殊的锁定机制,即在JVM中使用以允许线程之间的灵活同步。出于本节的目的,可以互换地阅读术语监视器和锁定。



然后它更进一步:



为避免在每个对象上都有监视器,JVM通常使用类或方法块中的标志来指示该项目已被锁定。大多数情况下,一段代码会在没有争用的情况下传输一些锁定的部分。因此,监护人标志足以保护这段代码。这称为平板显示器。但是,如果另一个线程想要访问某些被锁定的代码,则会发生真正的争用。 JVM现在必须创建(或膨胀)监视器对象以保存第二个线程,并安排信号机制来协调对代码段的访问。此监视器现在称为充气监视器。



以下是对从线程转储中看到的内容的更深入的解释。 Java线程由操作系统的本机线程实现。每个线程用粗体表示,例如:



Thread-1(TID:0x9017A0,sys_thread_t:0x23EAC8,状态:R,本机ID :0x6E4)prio = 5



*以下6项解释了这一点,因为我从示例中匹配它们,括号[]中的值:


  1. 名称[主题-1 ],

  2. 标识符[ 0x9017A0 ],

  3. JVM数据结构地址[ 0x23EAC8 ],

  4. 当前状态[ R ],

  5. 原生线程标识符[ 0x6E4 ],

  6. 和优先级[ 5 ]。

等待似乎是与jvm本身相关的守护程序线程不是应用程序线程持有。当你得到一个在Object.wait()时,这意味着守护程序线程,这里的终结器正在等待关于对象锁定的通知,在这种情况下,它会显示它正在等待的通知:
- 等待< 0x27ef0288>(一个java.lang.ref.ReferenceQueue $ Lock)



ReferenceQueue的定义是:
引用队列,在检测到适当的可达性更改后,垃圾收集器将附加的注册引用对象附加到该引用队列。



终结器线程运行,因此垃圾收集操作可以清理与对象关联的资源。如果我正确地看到它,终结器无法获得对此对象的锁定:java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)因为java对象正在运行一个方法,所以终结器线程是锁定,直到该对象完成它的当前任务。



此外,终结器不仅仅是要回收内存,它还要比清理资源更复杂。我需要对它进行更多的研究,但如果你有文件打开,套接字等...与对象方法有关,那么终结器也可以解决这些问题。



线程转储中的Object.wait之后的括号中的数字是多少?


它是线程内存中的指针。以下是更详细的说明:



C.4.1主题信息



主题部分的第一部分显示引发致命错误的线程如下:

 当前线程(0x0805ac88):JavaThreadmain[_thread_in_native,id = 21139] 
| | | | + - ID
| | | + ------------- state
| | + -------------------------- name
| + ------------------------------------键入
+ ------- -------------------------------------------指针

线程指针是指向Java VM内部线程结构的指针。除非您正在调试实时Java VM或核心文件,否则通常没有意义。



最后的描述来自:带有HotSpot VM的Java SE 6故障排除指南



这里有一些关于线程转储的链接:




I am trying to understand more about java, especially about memory management and threads. For this reason I have recently found interest in looking at thread dumps.

Here are few lines taken from a web app using VisualVM, a built-in tool for 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)

First I have questions about some variable names:

  • what does tid and nid mean?
  • What is the figure in squared parenthesis after Object.wait?

Then for the stack trace itself:

  • what does it mean waiting on <.....> (a java.lang....) and what's the number in <..>
  • what does it mean locked <.....> (a java.lang....) same question, what's in <..>

I thought that the word locked was related in someway to a wait condition, however, I was wrong. In fact, I am wondering why locked is repeated three times, but the thread is in runnable state as seen in the same dump:

"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)

Then last of all, this was the worst of them:

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

This thread is in runnable state, but it's waiting on condition. What condition and what is 0x00000?

Why the stack trace is so short without any evidence of the thread class?

If you could answer to all my questions I would be very grateful.

Thanks

解决方案

The TID is thead id and NID is: Native thread ID. This ID is highly platform dependent. It's the NID in jstack thread dumps. On Windows, it's simply the OS-level thread ID within a process. On Linux and Solaris, it's the PID of the thread (which in turn is a light-weight process). On Mac OS X, it is said to be the native pthread_t value.

Go to this link: Java-level thread ID: for a definition and a further explanation of these two terms.

On IBM's site I found this link: How to interpret a thread dump. that covers this in greater detail:

It explains what that waiting on means: A lock prevents more than one entity from accessing a shared resource. Each object in Java™ has an associated lock (gained by using a synchronized block or method). In the case of the JVM, threads compete for various resources in the JVM and locks on Java objects.

Then it describes the monitor as a special kind of locking mechanism that is used in the JVM to allow flexible synchronization between threads. For the purpose of this section, read the terms monitor and lock interchangeably.

Then it goes further:

To avoid having a monitor on every object, the JVM usually uses a flag in a class or method block to indicate that the item is locked. Most of the time, a piece of code will transit some locked section without contention. Therefore, the guardian flag is enough to protect this piece of code. This is called a flat monitor. However, if another thread wants to access some code that is locked, a genuine contention has occurred. The JVM must now create (or inflate) the monitor object to hold the second thread and arrange for a signaling mechanism to coordinate access to the code section. This monitor is now called an inflated monitor.

Here is a more in-depth explanation of what you are seeing on the lines from the thread dump. A Java thread is implemented by a native thread of the operating system. Each thread is represented by a line in bold such as:

"Thread-1" (TID:0x9017A0, sys_thread_t:0x23EAC8, state:R, native ID:0x6E4) prio=5

*The following 6 items explains this as I've matched them from the example, values in the brackets[]:

  1. name [Thread-1],
  2. identifier [0x9017A0],
  3. JVM data structure address [0x23EAC8],
  4. current state [R],
  5. native thread identifier [0x6E4],
  6. and priority [5].

The "wait on" appears to be a daemon thread associated with the jvm itself and not the application thread perse. When you get an "in Object.wait()", that means the daemon thread, "finalizer" here, is waiting on a notification about a lock on an object, in this case it shows you what notification it's waiting on: "- waiting on <0x27ef0288> (a java.lang.ref.ReferenceQueue$Lock)"

Definition of the ReferenceQueue is: Reference queues, to which registered reference objects are appended by the garbage collector after the appropriate reachability changes are detected.

The finalizer thread runs so the garbage collection operates to clean up resources associated with an object. If I'm seeing it corectly, the finalizer can't get the lock to this object: java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118) because the java object is running a method, so the finalizer thread is locked until that object is finished with it's current task.

Also, the finalizer isn't just looking to reclaim memory, it's more involved than that for cleaning up resources. I need to do more study on it, but if you have files open, sockets, etc... related to an objects methods, then the finalizer is going to work on freeing those items up as well.

What is the figure in squared parenthesis after Object.wait in the thread dump?

It is a pointer in memory to the thread. Here is a more detailed description:

C.4.1 Thread Information

The first part of the thread section shows the thread that provoked the fatal error, as follows:

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

The thread pointer is the pointer to the Java VM internal thread structure. It is generally of no interest unless you are debugging a live Java VM or core file.

This last description came from: Troubleshooting Guide for Java SE 6 with HotSpot VM

Here are a few more links on thread dumps:

这篇关于如何分析java线程转储?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆