`
jiagou
  • 浏览: 2537750 次
文章分类
社区版块
存档分类
最新评论

Thread Dump分析(转)

 
阅读更多

thread dump获取

1. 发送信号
* In Unix, use "kill -3 <pid>" where pid is the Process ID of the JVM.(kill 信号列表
* In Windows, press CTRL+BREAK on the window where the JVM is running.

2. jstack -l pid.

(1). jstack入口

  1. publicclassJStack{
  2. publicstaticvoidmain(String[]args)throwsException{
  3. ...
  4. Stringpid=args[optionCount];
  5. Stringparams[];
  6. if(locks){
  7. params=newString[]{"-l"};
  8. }else{
  9. params=newString[0];
  10. }
  11. runThreadDump(pid,params);
  12. ...
  13. }
  14. //Attachtopidandperformathreaddump
  15. privatestaticvoidrunThreadDump(Stringpid,Stringargs[])
  16. throwsException{
  17. VirtualMachinevm=null;
  18. try{
  19. vm=VirtualMachine.attach(pid);
  20. }catch(Exceptionx){
  21. ...
  22. }
  23. //CasttoHotSpotVirtualMachineasthisisimplementationspecific
  24. //method.
  25. InputStreamin=((HotSpotVirtualMachine)vm)
  26. .remoteDataDump((Object[])args);
  27. //readtoEOFandjustprintoutput
  28. byteb[]=newbyte[256];
  29. intn;
  30. do{
  31. n=in.read(b);
  32. if(n>0){
  33. Strings=newString(b,0,n,"UTF-8");
  34. System.out.print(s);
  35. }
  36. }while(n>0);
  37. in.close();
  38. vm.detach();
  39. }
(2).执行方式
LinuxVirtualMachine.execute
  1. /**
  2. *ExecutethegivencommandinthetargetVM.
  3. */
  4. @Override
  5. InputStreamexecute(Stringcmd,Object...args)throwsAgentLoadException,IOException
  6. {
  7. ...
  8. ints=socket();
  9. //connecttotargetVM
  10. try{
  11. connect(s,p);
  12. }
  13. catch(IOExceptionx){
  14. close(s);
  15. throwx;
  16. }
  17. IOExceptionioe=null;
  18. //connected-writerequest,发送command到targetjvm
  19. //<ver><cmd><args...>
  20. try{
  21. writeString(s,PROTOCOL_VERSION);
  22. writeString(s,cmd);
  23. for(inti=0;i<3;i++){
  24. if(i<args.length&&args[i]!=null){
  25. writeString(s,(String)args[i]);
  26. }
  27. else{
  28. writeString(s,"");
  29. }
  30. }
  31. }
  32. catch(IOExceptionx){
  33. ioe=x;
  34. }
  35. //Createaninputstreamtoreadreply.
  36. SocketInputStreamsis=newSocketInputStream(s);
  37. ....
  38. //Returntheinputstreamsothatthecommandoutputcanberead.
  39. returnsis;
  40. }
3. jvisualvm中来thread dump.

thread dump解析

头部信息

时间,jvm信息
  1. {code}
  2. 2011-11-0219:05:06
  3. FullthreaddumpJavaHotSpot(TM)ServerVM(16.3-b01mixedmode):
  4. {code}

线程info信息块

  1. {code}
  2. "Checkpointer"daemonprio=10tid=0x68ce1c00nid=0x7c11inObject.wait()[0x68b5c000]
  3. java.lang.Thread.State:WAITING(onobjectmonitor)
  4. atjava.lang.Object.wait(NativeMethod)
  5. -waitingon<0x740ad988>(ajava.lang.Object)
  6. atjava.lang.Object.wait(Object.java:485)
  7. atcom.sleepycat.je.utilint.DaemonThread.run(DaemonThread.java:163)
  8. -locked<0x740ad988>(ajava.lang.Object)
  9. atjava.lang.Thread.run(Thread.java:619)
  10. {code}

  1. "Checkpointer"daemonprio=10tid=0x68ce1c00nid=0x7c11inObject.wait()[0x68b5c000]

* 线程名称:Checkpointer
* 线程类型:daemon
* 优先级:10,默认是5
* jvm线程id:jvm内部线程的唯一标识,0x68ce1c00
* 对应系统线程id:和top命令查看的pid对应,不过一个是10进制,一个是16进制。0x7c11
* 线程状态:Object.wait().
* 起始栈地址

线程状态详解

Runnable
_The thread is either running or ready to run when it gets its CPU turn._
不解释。


Wait on condition
_The thread is either sleeping or waiting to be notified by another thread._
该状态出现在线程等待某个条件的发生或者sleep。
_最常见的情况是线程在等待网络的读写,比如当网络数据没有准备好读时,线程处于这种等待状态,而一旦有数据准备好读之后,线程会重新激活,读取并处理数据。_


Waiting for Monitor Entry and in Object.wait()

_The thread is waiting to get the lock for an object (some other thread may be holding the lock). This happens if two or more threads try to execute synchronized code. Note that the lock is always for an object and not for individual methods._
当一个线程申请进入临界区时,获取到monitor,线程将处于 “Runnable”的状态,否则,线程 DUMP会显示处于 “waiting for monitor entry”。
当线程获得了 Monitor,进入了临界区之后,如果发现线程继续运行的条件没有满足,它则调用对象(一般就是被 synchronized 的对象)的 wait() 方法,放弃了 Monitor,进入 “Wait Set”队列。只有当别的线程在该对象上调用了 notify() 或者 notifyAll() , “ Wait Set”队列中线程才得到机会去竞争,但是只有一个线程获得对象的 Monitor,恢复到运行态。在 “Wait Set”中的线程, DUMP中表现为: in Object.wait()。
例:

  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="color:#ff6666;">{code}
  2. "Timer-0"daemonprio=10tid=0x695c3000nid=0x7c00inObject.wait()[0x69468000]
  3. java.lang.Thread.State:TIMED_WAITING(onobjectmonitor)
  4. atjava.lang.Object.wait(NativeMethod)
  5. -waitingon<0x744f2850>(ajava.util.TaskQueue)###继续wait
  6. atjava.util.TimerThread.mainLoop(Timer.java:509)
  7. -locked<0x744f2850>(ajava.util.TaskQueue)###已经lock到0x744f2850
  8. atjava.util.TimerThread.run(Timer.java:462)
  9. {code}</span></span>
参见:http://jameswxx.iteye.com/blog/1041173

  1. {code}
  2. java.lang.Thread.State:WAITING(onobjectmonitor)
  3. <pstyle="margin-top:4px;margin-right:0px;margin-bottom:4px;margin-left:0px;padding-top:2px;padding-right:0px;padding-bottom:2px;padding-left:0px;">{code}</p>

线程状态运行:

WAITING||State || Description||

|blocked|This thread tried to enter a synchronized block, but the lock was taken by another thread. This thread is blocked until the lock gets released.|

|blocked (on thin lock)|This is the same state as blocked, but the lock in question is a thin lock.||waiting|This thread called Object.wait() on an object. The thread will remain there until some other thread sends a notification to that object.|

|sleeping|This thread called java.lang.Thread.sleep().||parked|This thread called java.util.concurrent.locks.LockSupport.park().||suspended|The thread's execution was suspended by java.lang.Thread.suspend() or a JVMTI agent call.|

  1. {code}
  2. atjava.lang.Object.wait(NativeMethod)
  3. -waitingon<0x740ad988>(ajava.lang.Object)###等待堆地址为0x740ad988的java.lang.Object对象的锁
  4. atjava.lang.Object.wait(Object.java:485)
  5. atcom.sleepycat.je.utilint.DaemonThread.run(DaemonThread.java:163)
  6. -locked<0x740ad988>(ajava.lang.Object)###hold住堆地址为0x740ad988的java.lang.Object对象的锁
  7. atjava.lang.Thread.run(Thread.java:619)
  8. {code}

thread dump使用

首先,thread dump是个瞬时数据,需要多个采样进行对比才能更好的发现问题

cpu飙高,load高,响应很慢

方案:
* 一个请求过程中多次dump

* 对比多次dump文件的runnable线程,如果执行的方法有比较大变化,说明比较正常。如果在执行同一个方法,就有一些问题了。

cpu使用率不高但是响应很慢

方案:
* 进行dump,查看是否有很多thread struck在了i/o、数据库等地方,定位瓶颈原因。

请求无法响应

方案:
* 多次dump,对比是否所有的runnable线程都一直在执行相同的方法,如果是的,恭喜你,锁住了!

死锁例子:

  1. publicclassDeadLock{
  2. publicstaticvoidmain(String[]args){
  3. finalObjectobj_1=newObject(),obj_2=newObject();
  4. Threadt1=newThread("t1"){
  5. @Override
  6. publicvoidrun(){
  7. synchronized(obj_1){
  8. try{
  9. Thread.sleep(3000);
  10. }catch(InterruptedExceptione){}
  11. synchronized(obj_2){
  12. System.out.println("threadt1done.");
  13. }
  14. }
  15. }
  16. };
  17. Threadt2=newThread("t2"){
  18. @Override
  19. publicvoidrun(){
  20. synchronized(obj_2){
  21. try{
  22. Thread.sleep(3000);
  23. }catch(InterruptedExceptione){}
  24. synchronized(obj_1){
  25. System.out.println("threadt2done.");
  26. }
  27. }
  28. }
  29. };
  30. t1.start();
  31. t2.start();
  32. }
  33. }

thread dump

  1. "t2"prio=10tid=0x09d0d000nid=0x1f17waitingformonitorentry[0x71dad000]
  2. java.lang.Thread.State:BLOCKED(onobjectmonitor)
  3. atDeadLock$2.run(DeadLock.java:30)
  4. -waitingtolock<0x9f4c29b0>(ajava.lang.Object)
  5. -locked<0x9f4c29b8>(ajava.lang.Object)
  6. Lockedownablesynchronizers:
  7. -None
  8. "t1"prio=10tid=0x09d22c00nid=0x1f16waitingformonitorentry[0x71dfe000]
  9. java.lang.Thread.State:BLOCKED(onobjectmonitor)
  10. atDeadLock$1.run(DeadLock.java:15)
  11. -waitingtolock<0x9f4c29b8>(ajava.lang.Object)
  12. -locked<0x9f4c29b0>(ajava.lang.Object)
  13. Lockedownablesynchronizers:
  14. -None
  15. FoundoneJava-leveldeadlock:
  16. =============================
  17. "t2":
  18. waitingtolockmonitor0x09c32f18(object0x9f4c29b0,ajava.lang.Object),
  19. whichisheldby"t1"
  20. "t1":
  21. waitingtolockmonitor0x09c32360(object0x9f4c29b8,ajava.lang.Object),
  22. whichisheldby"t2"
  23. Javastackinformationforthethreadslistedabove:
  24. ===================================================
  25. "t2":
  26. atDeadLock$2.run(DeadLock.java:30)
  27. -waitingtolock<0x9f4c29b0>(ajava.lang.Object)
  28. -locked<0x9f4c29b8>(ajava.lang.Object)
  29. "t1":
  30. atDeadLock$1.run(DeadLock.java:15)
  31. -waitingtolock<0x9f4c29b8>(ajava.lang.Object)
  32. -locked<0x9f4c29b0>(ajava.lang.Object)
  33. Found1deadlock.

查找占用cpu最多的线程信息

方案:
# dump thread
# 找到导致cpu高的线程:top -H -p pid,对应的线程id是十进制的。(top命令详解见:http://www.w3pop.com/learn/view/p/1/o/1/doc/linux_cmd_top/)
# 十进制转十六进制
# 从dump中找到对应的线程

转自http://blog.csdn.net/wanyanxgf/article/details/6944987
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics