2

我在这里使用 Ubuntu(服务器版)在 Tomcat6 上运行了一个 Java Web 应用程序。1-3天后,应用程序变得很慢,所以我在重新启动tomcat后创建了一个threaddump,当应用程序开始变慢时创建了另一个:

重新启动后的线程转储:

3天后的Threaddump(应用程序现在很慢):

从我发布的转储中,我可以看到有很多线程似乎由于某种原因没有终止。不幸的是,我不知道哪些(类名?)以及为什么。在控制台上使用top显示“VIRT”的值从〜800(重新启动后)上升到超过4000(3天后)。

我怎样才能更好地解释这些转储?我已经尝试将它们加载到 TDA 中,但没有成功(TDA 似乎没有将它们识别为转储)。

也许有人已经在垃圾场中看到了发生了什么?

4

4 回答 4

5

在 jstack 文本文件中,我看到许多线程挂在 BCI(字节码解释器)中,可能正在解释您的代码。它似乎没有表明它在您的代码中解释的位置。

确实说你有一个死锁条件。

在 .out 文件中,我查找了看起来像应用程序代码的内容。我看到它挂在

  • EventProcessingThreadImpl.run:479(2 个线程)

  • GC.java:100(1 个线程)在 GC 中等待释放某些东西,以便 GC 可以继续。

  • 在 ThreadPoolExecutor.java:907 中,许多线程处于不安全状态,等待同步器,试图读取作业队列

  • 我还看到了很多样板文件——等待分配工作的线程、可运行的线程、等待邮件等。

这有什么帮助吗?

添加:

好的,我搜索了您的代码并在三个线程上找到了它,如图所示,在每个线程下面我给出了一个初步的解释。

(另外,请注意有关使用 jstack 查找死锁的链接。)

----------------- 20607 -----------------
__pthread_cond_wait + 0xcc
_ZN13ObjectMonitor4waitElbP6Thread + 0x60a
_ZN18ObjectSynchronizer4waitE6HandlelP6Thread + 0x53
JVM_MonitorWait + 0x1e7
<Unknown compiled code>
* java.lang.Object.wait() bci:2 line:485 (Interpreted frame)
* org.zkoss.zk.ui.impl.EventProcessingThreadImpl.doSuspend0(java.lang.Object) bci:143 line:219 (Interpreted frame)
* org.zkoss.zk.ui.impl.EventProcessingThreadImpl.doSuspend(java.lang.Object) bci:7 line:185 (Interpreted frame)
* org.zkoss.zk.ui.impl.UiEngineImpl.wait(java.lang.Object) bci:198 line:1471 (Interpreted frame)
* org.zkoss.zk.ui.Executions.wait(java.lang.Object) bci:4 line:702 (Interpreted frame)
* org.zkoss.zul.Window.enterModal() bci:22 line:619 (Interpreted frame)
* org.zkoss.zul.Window.doModal() bci:67 line:551 (Interpreted frame)
* org.zkoss.zul.Messagebox.show(java.lang.String, java.lang.String, int, java.lang.String, int,     org.zkoss.zk.ui.event.EventListener) bci:343 line:274 (Interpreted frame)
* org.zkoss.zul.Messagebox.show(java.lang.String, java.lang.String, int, java.lang.String) bci:6 line:128 (Interpreted frame)
* com.smampi.web.view.client.ClientController$5.onEvent(org.zkoss.zk.ui.event.Event) bci:8 line:417 (Interpreted frame)
* org.zkoss.zk.ui.impl.EventProcessor.process0(org.zkoss.zk.ui.ext.Scope) bci:384 line:192 (Compiled frame)
????????

线程 20607 位于 com.smampi.web.view.client.ClientController$5.onEvent 第 128 行(我猜)。它正在显示一个模式消息框并等待它被回答。

----------------- 20878 -----------------
__pthread_cond_wait + 0xcc
_ZN13ObjectMonitor4waitElbP6Thread + 0x60a
_ZN18ObjectSynchronizer4waitE6HandlelP6Thread + 0x53
JVM_MonitorWait + 0x1e7
<Unknown compiled code>
* java.lang.Object.wait() bci:2 line:485 (Interpreted frame)
* org.zkoss.zk.ui.impl.EventProcessingThreadImpl.doSuspend0(java.lang.Object) bci:143 line:219 (Interpreted frame)
* org.zkoss.zk.ui.impl.EventProcessingThreadImpl.doSuspend(java.lang.Object) bci:7 line:185 (Interpreted frame)
* org.zkoss.zk.ui.impl.UiEngineImpl.wait(java.lang.Object) bci:198 line:1471 (Interpreted frame)
* org.zkoss.zk.ui.Executions.wait(java.lang.Object) bci:4 line:702 (Interpreted frame)
* org.zkoss.zul.Window.enterModal() bci:22 line:619 (Interpreted frame)
* org.zkoss.zul.Window.doModal() bci:67 line:551 (Interpreted frame)
* org.zkoss.zul.Messagebox.show(java.lang.String, java.lang.String, int, java.lang.String, int, org.zkoss.zk.ui.event.EventListener) bci:343 line:274 (Interpreted frame)
* org.zkoss.zul.Messagebox.show(java.lang.String, java.lang.String, int, java.lang.String) bci:6 line:128 (Interpreted frame)
* com.smampi.web.view.client.ClientController$5.onEvent(org.zkoss.zk.ui.event.Event) bci:8 line:417 (Interpreted frame)
* org.zkoss.zk.ui.impl.EventProcessor.process0(org.zkoss.zk.ui.ext.Scope) bci:384 line:192 (Compiled frame)
????????

线程 20878 也显示了一个消息框,但在第 417 行(我猜)

----------------- 22792 -----------------
__pthread_cond_wait + 0xcc
_ZN7Monitor5ILockEP6Thread + 0xb9
_ZN7Monitor4lockEP6Thread + 0xf2
_ZN7Monitor4lockEv + 0x28
_ZN18GenCollectorPolicy17mem_allocate_workEmbPb + 0xca
_ZN16GenCollectedHeap12mem_allocateEmbbPb + 0x38
_ZN13CollectedHeap26common_mem_allocate_noinitEmbP6Thread + 0x9a
_ZN13instanceKlass17allocate_instanceEP6Thread + 0x7d
_ZN18InterpreterRuntime4_newEP10JavaThreadP19constantPoolOopDesci + 0xda
* com.sun.mail.util.SocketFetcher.startTLS(java.net.Socket, java.lang.String, java.util.Properties, java.lang.String) bci:378 line:413 (Interpreted frame)
* com.sun.mail.iap.Protocol.startTLS(java.lang.String) bci:23 line:377 (Interpreted frame)
* com.sun.mail.imap.protocol.IMAPProtocol.startTLS() bci:3 line:734 (Interpreted frame)
* com.sun.mail.imap.IMAPStore.login(com.sun.mail.imap.protocol.IMAPProtocol, java.lang.String, java.lang.String) bci:24 line:676 (Interpreted frame)
* com.sun.mail.imap.IMAPStore.protocolConnect(java.lang.String, int, java.lang.String, java.lang.String) bci:343 line:643 (Interpreted frame)
* javax.mail.Service.connect(java.lang.String, int, java.lang.String, java.lang.String) bci:380 line:295 (Interpreted frame)
* com.smampi.web.model.mail.server.MailServer.connect() bci:427 line:514 (Interpreted frame)
* com.smampi.web.model.mail.server.MailServer$1.closed(javax.mail.event.ConnectionEvent) bci:10 line:593 (Interpreted frame)
* javax.mail.event.ConnectionEvent.dispatch(java.lang.Object) bci:55 line:96 (Interpreted frame)

线程 22792 正在尝试从 com.smampi.web.model.mail.server.MailServer.connect 第 514 行进行邮件服务连接,并且从 com.smampi.web.model.mail.server.MailServer$1.close 调用在第 593 行。为此,它看起来正在等待另一个线程停止垃圾收集,因此它可以为新线程分配内存,以便它可以执行“startTLS”(用于将纯文本链接升级为加密链接)所以它可以进行邮件服务连接。

这有什么启示吗?

于 2011-10-04T14:39:52.607 回答
0

我看到很多线程试图建立 SSL 上下文:

“JavaMail-EventQueue”守护进程prio=10 tid=0x00007f9f10416000 nid=0x54c6 等待监视器条目[0x00007f9e3e92d000]
   java.lang.Thread.State: BLOCKED (在对象监视器上)
    在 sun.security.provider.NativePRNG$RandomIO.implNextBytes(NativePRNG.java:255)
    - 等待锁定(java.lang.Object)
    在 sun.security.provider.NativePRNG$RandomIO.access$200(NativePRNG.java:108)
    在 sun.security.provider.NativePRNG.engineNextBytes(NativePRNG.java:97)
    在 java.security.SecureRandom.nextBytes(SecureRandom.java:433)
    - 锁定(java.security.SecureRandom)
    在 java.security.SecureRandom.next(SecureRandom.java:455)
    在 java.util.Random.nextInt(Random.java:189)
    在 com.sun.net.ssl.internal.ssl.SSLContextImpl.engineInit(SSLContextImpl.java:82)
    在 javax.net.ssl.SSLContext.init(SSLContext.java:248)
    在 com.sun.mail.util.MailSSLSocketFactory.newAdapteeFactory(MailSSLSocketFactory.java:130)
    - 锁定(com.sun.mail.util.MailSSLSocketFactory)
    在 com.sun.mail.util.MailSSLSocketFactory.(MailSSLSocketFactory.java:119)
    在 com.sun.mail.util.MailSSLSocketFactory.(MailSSLSocketFactory.java:94)
    在 com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:413)
    在 com.sun.mail.iap.Protocol.startTLS(Protocol.java:377)
    - 锁定(com.sun.mail.imap.protocol.IMAPProtocol)
    在 com.sun.mail.imap.protocol.IMAPProtocol.startTLS(IMAPProtocol.java:734)
    在 com.sun.mail.imap.IMAPStore.login(IMAPStore.java:676)
    在 com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:643)
    - 锁定(com.sun.mail.imap.IMAPStore)
    在 javax.mail.Service.connect(Service.java:295)
    - 锁定(com.sun.mail.imap.IMAPStore)
    在 com.smampi.web.model.mail.server.MailServer.connect(MailServer.java:514)
    在 com.smampi.web.model.mail.server.MailServer$1.closed(MailServer.java:593)
    在 javax.mail.event.ConnectionEvent.dispatch(ConnectionEvent.java:96)
    在 javax.mail.EventQueue.run(EventQueue.java:134)
    在 java.lang.Thread.run(Thread.java:662)

我经常看到服务器在 SSL 设置期间变得莫名其妙地变慢(无论是作为服务器还是作为客户端),当操作系统的可用熵变得非常低时(即操作系统无法生成任何高质量的随机数)更多的)。

尝试显示/proc/sys/kernel/random/entropy_avail使用的内容

cat /proc/sys/kernel/random/entropy_avail

这应该告诉您操作系统目前可以提供多少随机数据,通常应该至少有数百个。如果它始终为 0 或非常接近,那么您遇到了问题,需要引入另一个熵源。

话又说回来,也可能是相反的情况:该连接的另一端可能在收集熵时遇到问题,并且可能回答缓慢。

于 2011-10-04T13:28:09.530 回答
0

您有很多(数千个?)处于 WAITING 状态的线程。在这里阅读各种线程状态:http: //download.oracle.com/javase/1,5,0/docs/api/java/lang/Thread.State.html

这是个问题。您需要找出为什么您的应用会创建这么多线程而不是销毁它们。

您还有很多称为“JavaMail-EventQueue”的线程。找出邮件生命周期未完成的原因。将一些日志语句添加到您对 JavaMail 的使用中,您可能会发现某些操作经常无法完成。

于 2011-10-04T13:32:15.457 回答
0

我的猜测是,您不小心尝试将 TLS(加密)与不期望加密流量的服务进行通信,因此您有许多线程在等待正确的响应,而这些响应永远不会到来。

您确定您为此服务使用了正确的端口号吗?

于 2011-10-17T23:09:58.747 回答