如何在spring + tomcat应用程序中找到线程泄漏

时间:2019-01-18 10:13:35

标签: java spring tomcat threadpool

我有一个spring boot(1.5.2)Web应用程序,它在tomcat(8.5)中作为唯一的Web应用程序运行。 JVM(openjdk 1.8.0_181)中的线程总数几乎(尽管不是完全)以恒定的速率单调增加,从开始的几百个增加到一周的约3000个。到那时,大多数线程堆栈跟踪看起来像:

WAITING Thread[pool-917-thread-1,5,main]
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
java.lang.Thread.run(Thread.java:748)

应用程序在其他方面可以正常运行,这些线程似乎并不会占用太多内存(至少与应用程序通常消耗的数十GB内存相比),但是它们的存在表明应用程序内部存在一些隐藏的泄漏。在撰写本文时,我目前找不到处于不同状态的名为pool-.*的线程,因此在进入僵尸程序之前我不知道它们通常会做什么。在没有重新启动tomcat的情况下,永远不会重新部署该应用程序。

我的问题是,是否有人遇到过类似的问题,以及如何解决这些问题,如果没有,我如何诊断为什么创建了这些线程却之后又未将其删除。

1 个答案:

答案 0 :(得分:0)

以这种方式产生线程的最可能原因:

  1. Tomcat配置错误,例如executor maxThreads从默认值200设置为过高的值。
  2. 应用程序代码创建一个ubound线程池,例如Executors.newCachedThreadPool()遇到线程峰值。
  3. 在应用程序重新部署期间,未正确部署由未部署的应用程序创建的线程池。参见this answer
  4. 应用程序代码使用new Thread()创建线程。

第4点不太可能出现,因为堆栈跟踪显示java.util.concurrent.ThreadPoolExecutor。查找创建带有前缀pool-的线程的池(grep应用程序代码和pool-的Tomcat配置)。然后盖好游泳池。