java tid nidhreaddump日志中的tid和nid的区别

三个实例演示&Java&Thread&Dump&日志分析
jstack Dump
日志文件中的线程状态
dump 文件里,值得关注的线程状态有:
死锁,Deadlock(重点关注)&
执行中,Runnable&
等待资源,Waiting
on condition(重点关注)&
等待获取监视器,Waiting
on monitor entry(重点关注)
暂停,Suspended
对象等待中,Object.wait()
或 TIMED_WAITING
阻塞,Blocked(重点关注)&&
停止,Parked
下面我们先从第一个例子开始分析,然后再列出不同线程状态的含义以及注意事项,最后再补充两个实例。
综合示范一:Waiting
to lock 和 Blocked
实例如下:
"RMI TCP Connection(2.16.5.25" daemon prio=10
tid=0x0000 nid=0x55ae&waiting
for monitor entry&[0x04000]
&java.lang.Thread.State:&BLOCKED
(on object monitor)
org.apache.log4j.Category.callAppenders(Category.java:201)
&0xacf4d0c0&&(a
org.apache.log4j.Logger)
org.apache.log4j.Category.forcedLog(Category.java:388)
at org.apache.log4j.Category.log(Category.java:853)
mons.logging.impl.Log4JLogger.warn(Log4JLogger.java:234)
com.mon.lang.cache.remote.SpyMemcachedClient.get(SpyMemcachedClient.java:110)
1)线程状态是&Blocked,阻塞状态。说明线程等待资源超时!
2)“&waiting
&0xacf4d0c0&”指,线程在等待给这个&0xacf4d0c0
地址上锁(英文可描述为:trying to
obtain&&0xacf4d0c0&lock)。
3)在 dump 日志里查找字符串&0xacf4d0c0,发现有大量线程都在等待给这个地址上锁。如果能在日志里找到谁获得了这个锁(如locked
&&0xacf4d0c0&&),就可以顺藤摸瓜了。
4)“waiting
for monitor entry”说明此线程通过 synchronized(obj) {……}
申请进入了临界区,从而进入了下图1中的“Entry Set”队列,但该 obj 对应的 monitor 被其他线程拥有,所以本线程在
Entry Set 队列中等待。
5)第一行里,"RMI
TCP Connection(2.16.5.25"是&Thread
Name&。tid指Java Thread
id。nid指native线程的id。prio是线程优先级。[0x04000]是线程栈起始地址。
Dump文件中的线程状态含义及注意事项
含义如下所示:
Deadlock:死锁线程,一般指多个线程调用间,进入相互资源占用,导致一直等待无法释放的情况。
Runnable:一般指该线程正在执行状态中,该线程占用了资源,正在处理某个请求,有可能正在传递SQL到数据库执行,有可能在对某个文件操作,有可能进行数据类型等转换。
Waiting on condition:等待资源,或等待某个条件的发生。具体原因需结合
stacktrace来分析。
如果堆栈信息明确是应用代码,则证明该线程正在等待资源。一般是大量读取某资源,且该资源采用了资源锁的情况下,线程进入等待状态,等待资源的读取。
又或者,正在等待其他线程的执行等。
如果发现有大量的线程都在处在 Wait on condition,从线程
stack看,正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。
一种情况是网络非常忙,几乎消耗了所有的带宽,仍然有大量数据等待网络读写;
另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。
另外一种出现 Wait on condition的常见情况是该线程在 sleep,等待
sleep的时间到了时候,将被唤醒。
Blocked:线程阻塞,是指当前线程执行过程中,所需要的资源长时间等待却一直未能获取到,被容器的线程管理器标识为阻塞状态,可以理解为等待资源超时的线程。
Waiting for monitor entry 和 in Object.wait():Monitor是
Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个
monitor。从下图1中可以看出,每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active
Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait
Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在
“Wait Set”中等待的线程状态是 “in Object.wait()”。
<img STYLE="BorDer-BoTToM: 0 BorDer-LeFT: 0 pADDinG-BoTToM: 0 MArGin: 0 pADDinG-LeFT: 0 pADDinG-riGHT: 0 BorDer-Top: 0 BorDer-riGHT: 0 pADDinG-Top: 0px" ALT="/cnblogs_com/zhengyun_ustc/255879/o_clipboard" src="/blog7style/images/common/sg_trans.gif" real_src ="/cnblogs_com/zhengyun_ustc/255879/o_clipboard%20-%20%E5%89%AF%E6%9C%AC039.png"
TITLE="三个实例演示&Java&Thread&Dump&日志分析" />
图1 A Java Monitor
综合示范二:Waiting
on condition&和&TIMED_WAITING
实例如下:
"RMI TCP Connection(idle)" daemon prio=10 tid=0x0e800
nid=0x56b2&waiting
on condition&[0x0a59000]
&java.lang.Thread.State:&TIMED_WAITING
at sun.misc.Unsafe.park(Native Method)
to wait for
&&0xacd84de8&&(a
java.util.concurrent.SynchronousQueue$TransferStack)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:424)
java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:323)
java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:874)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:945)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:662)
1)“TIMED_WAITING
(parking)”中的 timed_waiting
指等待状态,但这里指定了时间,到达指定的时间后自动退出等待状态;parking指线程处于挂起中。
2)“waiting
on condition”需要与堆栈中的“parking
to wait for
&&0xacd84de8&&(a
java.util.concurrent.SynchronousQueue$TransferStack)”结合来看。首先,本线程肯定是在等待某个条件的发生,来把自己唤醒。其次,SynchronousQueue
并不是一个队列,只是线程之间移交信息的机制,当我们把一个元素放入到 SynchronousQueue
中时必须有另一个线程正在等待接受移交的任务,因此这就是本线程在等待的条件。
3)别的就看不出来了。
综合示范三:in
Obejct.wait()&和&TIMED_WAITING
实例如下:
RenewClean-[172.16.5.19:28475]"
daemon prio=10 tid=0x8800 nid=0xb09&in
Object.wait()&[0xbd0000]
&java.lang.Thread.State:&TIMED_WAITING
(on object monitor)
at java.lang.Object.wait(Native Method)
on &0x2478& (a
java.lang.ref.ReferenceQueue$Lock)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
&0x2478& (a
java.lang.ref.ReferenceQueue$Lock)
sun.rmi.transport.DGCClient$EndpointEntry$RenewCleanThread.run(DGCClient.java:516)
at java.lang.Thread.run(Thread.java:662)
1)“TIMED_WAITING
(on object
monitor)”,对于本例而言,是因为本线程调用了&java.lang.Object.wait(long
timeout) 而进入等待状态。
2)“Wait Set”中等待的线程状态就是“&in&Object.wait()&”。当线程获得了
Monitor,进入了临界区之后,如果发现线程继续运行的条件没有满足,它则调用对象(一般就是被 synchronized 的对象)的
wait() 方法,放弃了 Monitor,进入 “Wait Set”队列。只有当别的线程在该对象上调用了 notify() 或者
notifyAll() ,“ Wait Set”队列中线程才得到机会去竞争,但是只有一个线程获得对象的
Monitor,恢复到运行态。&
3)RMI RenewClean 是 DGCClient 的一部分。&指的是
Distributed GC,即分布式垃圾回收。
4)请注意,是先&locked
&0x2478&,后&waiting
&0x2478&,之所以先锁再等同一个对象,请看下面它的代码实现:
static private class &Lock { };
private Lock lock = new Lock();
public Reference
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。yuangeqingtia 的BLOG
用户名:yuangeqingtia
文章数:175
访问量:95656
注册日期:
阅读量:5863
阅读量:12276
阅读量:351556
阅读量:1049834
51CTO推荐博文
系统跑的是java tomcat,要触发tomcat thread dump很简单,要先找到tomcat对应到饿进程Id.使用命令ps -ef|grep tomcat然后给这个进程发送一个QUIT的信号,让其触发线程的dumpkill -3 pidtomcat会把thread dump 的信息输出到控制台:/tomcathome/logs/catalina.out文件下。查看此文件这里的tid :对应的是linux操作系统下的轻量级进程号,这里为16进制,转换到10进制nid是jvm的jmm内存规范中的唯一地址定位。此文件中最后还有系统对内存的使用情况。本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:┆阅读(0)┆评论(0)<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&Linux下Java线程详细监控和其dump的分析使用—-分析Java性能瓶颈 - 为程序员服务
Linux下Java线程详细监控和其dump的分析使用—-分析Java性能瓶颈
这里对linux下、sun(oracle) JDK的线程资源占用问题的查找步骤做一个小结;
linux环境下,当发现java进程占用CPU资源很高,且又要想更进一步查出哪一个java线程占用了CPU资源时,按照以下步骤进行查找:
(一):通过【 top
-p 12377 -H】 查看java进程的有哪些线程的运行情况;
和通过【jstack 12377 & stack.log】生成Java线程的dump详细信息;
先用top命令找出占用资源厉害的java进程id,如图:# top
如上图所示,java的进程id为&#&#8242;,接下来用top命令单独对这个进程中的所有线程作监视:
-p 52554 -H
top视图里面里面可以通过快捷键依次b ,x高亮显示top的列找出需要的线程,默认CPU排序,Shift+& ,Shift+&可以左右移动高亮排序的列;
如图:(这时就看出来哪个java线程CPU高,哪个线程内存用的多)
如上图所示,linux下,所有的java内部线程,其实都对应了一个进程id,也就是说,linux上的sun jvm将java程序中的线程映射为了操作系统进程;我们看到,占用CPU资源最高的那个进程id是&#&#8242;,这个进程id对应java线程信息中的&#8217;nid&#8217;(&#8216;n&#8217; stands for &#8216;native&#8217;);
(1)要想找到到底是哪段具体的代码占用了如此多的资源,先使用jstack打出当前栈信息到一个文件里, 比如stack.log:
jstack 52554 & stack.log
然后使用&#8217;jtgrep&#8217;脚本把这个进程号为&#&#8242;的java线程在stack.log中抓出来:
jtgrep 9757 stack.log
其中,&#8217;jtgrep&#8217;是自己随便写的一个shell脚本:
nid=`python -c
"print hex($1)" `
-i $nid $2
道理很简单,就是 把&#&#8242;转换成16进制后,直接grep stack.可以看到,被grep出的那个线程的nid=0x3c39,正好是15417的16进制表示。
(2) 通过(windows程序&#8211;&计算器),选择程序员计算器将进程ID转换成16进制 到dump里面的nid 就可以搜索到
&#8220;http-nio-8080-exec-25&#8243; daemon prio=10 tid=0xb4800 nid=0x1ce5 waiting on condition [0xcf000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
&#8211; parking to wait for
&0x3ec8& (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)
at java.util.concurrent.LinkedBlockingQueue.take(Unknown Source)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:104)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:32)
at java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
(二)第二种通过 Java visualMv结合 jconsole.exe
工具即可查看如图所示;(第一种方式可能更准确一些)
三:在Java Visualvm工具里面安装JTA插件,分析线程dump文件,注意,正常阶段的dump文件与非正常时期的Dump文件进行比较更容易分析出问题:
(1)下载:https://java.net/projects/tda/downloads/directory/visualvm
(2)安装与使用:
(3)使用:
四:直接通过tda-bin-2.2\bin\tda.sh 来分析导出ThreadDump文件;(在没有JMX监控的情况下手动查看threadDump信息)
下载地址:https://java.net/projects/tda/downloads/directory/visualvm
IT技术文章geek资讯
原文地址:, 感谢原作者分享。
您可能感兴趣的代码

我要回帖

更多关于 thread dump 分析工具 的文章

 

随机推荐