当JVM在GC中花费时间时,线程转储是什么样的

在分析Java应用程序时,我注意到有趣的事实。 当JVM处于死亡线程转储的GC螺旋时,它看起来像:

"1304802943@qtp-393978767-9985" prio=10 tid=0x00007f3ed02dd000 nid=0x74e7 in Object.wait() [0x000000004febb000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:626) - locked  (a org.mortbay.thread.QueuedThreadPool$PoolThread) "26774405@qtp-393978767-9984" prio=10 tid=0x00007f3ee4b37000 nid=0x74e6 in Object.wait() [0x0000000045d1a000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:626) - locked  (a org.mortbay.thread.QueuedThreadPool$PoolThread) "764808089@qtp-393978767-9983" prio=10 tid=0x00007f3ee4c50000 nid=0x74e5 in Object.wait() [0x000000004ad6a000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:626) - locked  (a org.mortbay.thread.QueuedThreadPool$PoolThread) 

因此, TIMED_WAITING状态中有很multithreading。 从理论上讲,这种情况很容易在正常运行的应用程序中找到(应用程序此刻根本没有任何传入请求),但我甚至找不到单个请求调度线程做一些有用的事情(名义命中率约为100 hps)。

这种行为是否与GC有关,或者只是巧合?

回答问题的标题:

当JVM在GC中花费时间时,线程转储是什么样的?

答案是:你没有办法获得这种转储(以通常的方式)。

JVM在到达安全点之后才处理线程转储请求,这在GC中是不可能发生的。

但是在这篇文章中提到的未记录的JVMTI函数AsyncGetCallTrace的帮助下,有一种获取活动GC的线程转储的作弊方法:

http://jeremymanson.blogspot.com/2010/07/why-many-profilers-have-serious.html

它还暗示Oracle Solaris Studio可用于采用此类混合本机/ java线程转储。

尝试jmap -histo:随着时间的推移,你可以比较输出,看看哪些对象类型正在增长。

您需要为jmap安装JDK。 http://docs.oracle.com/javase/6/docs/technotes/tools/share/jmap.html

一个警告,jmap是密集的,它将在它运行时暂停所有线程,这应该只有几秒钟。 进程可以核心转储,因为它是密集的,通常它是快速和安全的,但我已经看到它锁定或杀死大型应用程序,多gig堆。

我的猜测是你有一个线程池正在等待一些事情要做。 如果您的流程效率很高,并且每秒甚至有100个请求,那么即使是一个线程执行某些操作也可能无法捕获。 我建议你看一下你的进程的CPU负载。 如果是50%,你有50%的机会找到一个线程(可能不是请求线程)做某事。

如果你想看看你的服务器花了多少时间,我会尝试像VisualVM这样的分析器,或像YourKit这样的商业分析器。

谷歌搜索你的代码,我发现了一个不同的版本http://grepcode.com/file/repo1.maven.org/maven2/org.mortbay.jetty/jetty-util/7.0.0.pre5/org/mortbay /thread/QueuedThreadPool.java然而我怀疑你的线程在这个块中是TIMED_WAIT int run#()方法

  // We are idle // wait for a dispatched job synchronized (this) { if (_job==null) this.wait(getMaxIdleTimeMs()); job=_job; _job=null; }