4

在分析 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 <0x00000007aed40048> (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 <0x00000007aed83aa0> (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 <0x00000007aed5c448> (a org.mortbay.thread.QueuedThreadPool$PoolThread)

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

这种行为与 GC 有什么关系,还是只是巧合?

4

3 回答 3

3

只回答问题的标题:

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

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

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

但是有一种作弊方法可以借助本文中提到的未记录的 JVMTI 函数 AsyncGetCallTrace 来获取活动 GC 的线程转储:

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

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

于 2012-12-29T17:55:55.837 回答
1

试试 jmap -histo:live over time,你可以比较输出,看看哪些对象类型在增长。

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

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

于 2011-12-30T16:57:35.477 回答
0

我的猜测是你有一个线程池正在等待做某事。如果您的流程是高效的并且您每秒甚至有 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 在他的 run() 方法中

                // We are idle
                // wait for a dispatched job
                synchronized (this)
                {
                    if (_job==null)
                        this.wait(getMaxIdleTimeMs());
                    job=_job;
                    _job=null;
                }
于 2011-12-07T08:51:40.230 回答