jstack现状
当我们用jstack排查线程栈问题的时候,我们经常会遇到许多相同的线程栈,尤其是当我们使用了线程池或者系统框架使用了线程池的时候,许多重复的栈桢充满着整个屏幕,想要找到我们需要的信息比较麻烦
执行:
jstack 12321
结果:
"qtp837692250-110" #110 prio=5 os_prio=31 tid=0x00007fdc80c4d000 nid=0x7703 waiting on condition [0x0000700006d13000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006c1fa59a0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at org.eclipse.jetty.util.BlockingArrayQueue.poll(BlockingArrayQueue.java:337)
at org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll(QueuedThreadPool.java:517)
at org.eclipse.jetty.util.thread.QueuedThreadPool.access$600(QueuedThreadPool.java:39)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:563)
at java.lang.Thread.run(Thread.java:748)
"qtp837692250-109" #109 prio=5 os_prio=31 tid=0x00007fdc812c6000 nid=0x7603 waiting on condition [0x0000700006c10000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006c1fa59a0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at org.eclipse.jetty.util.BlockingArrayQueue.poll(BlockingArrayQueue.java:337)
at org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll(QueuedThreadPool.java:517)
at org.eclipse.jetty.util.thread.QueuedThreadPool.access$600(QueuedThreadPool.java:39)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:563)
at java.lang.Thread.run(Thread.java:748)
"Druid-ConnectionPool-Create-927542454" #41 daemon prio=5 os_prio=31 tid=0x00007fdc7e995000 nid=0x620f waiting on condition [0x00007000056d1000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006c173cf10> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2443)
"Abandoned connection cleanup thread" #37 daemon prio=5 os_prio=31 tid=0x00007fdc7e992800 nid=0x9c03 in Object.wait() [0x00007000055ce000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x00000006c131aa90> (a java.lang.ref.ReferenceQueue$Lock)
at com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:43)
"container-0" #36 prio=5 os_prio=31 tid=0x00007fdc7e992000 nid=0x1207 waiting on condition [0x00007000054cb000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.catalina.core.StandardServer.await(StandardServer.java:408)
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer$1.run(TomcatWebServer.java:181)
"ContainerBackgroundProcessor[StandardEngine[Tomcat]]" #35 daemon prio=5 os_prio=31 tid=0x00007fdc7e990800 nid=0x100f waiting on condition [0x00007000053c8000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1365)
at java.lang.Thread.run(Thread.java:748)
awk优化
许多时候我们的系统都是跑在linux下面,于是我们可以通过linux的awk命令来把这些栈桢数据“合并”一下,然后用浏览器来查看
执行:
jstack 12321| awk '{total=NR;line[NR]=$0;}END{for(i=total;i>0;i--)print line[i];}'|awk '{
gsub("<", "[", $0);
gsub(">", "]", $0);
if($0=="")
str="";
else{
if(single[str"\r\n"$0]==""){
son[str]=son[str]"##"str"\r\n"$0;
single[str"\r\n"$0]="n";
}
str=str"\r\n"$0;
}
leaf[str]++;
name[str]=$0;
} END {
stack[0]="";
for(;;){
if(length(stack) == 0) break;
s=stack[length(stack)-1];
delete stack[length(stack)-1];
if(s=="/") {
print "</frame>";
continue;
}
print "<frame info='\''"name[s]"'\'' cnt='\''"leaf[s]"'\''>";
stack[length(stack)]="/";
if(son[s] != ""){
split(son[s], arr, "##");
for(i=length(arr);i>=0;i--){
for(j=i-1;j>=0;j--){
if(leaf[arr[j]]<leaf[arr[i]]||((leaf[arr[j]]==leaf[arr[i]])&&(length(arr[j])>length(arr[i])))){
temp=arr[j];
arr[j]=arr[i];
arr[i]=temp;
}
}
};
for(i=length(arr);i>=0;i--){
if(arr[i] != "")
stack[length(stack)]=arr[i];
}
}
}
}' > /tmp/12321.xml
然后我们用浏览器打开/tmp/12321.xml文件
是不是清晰很多呢