How to locate thread leak in spring + tomcat application












1















I have a spring boot (1.5.2) web application that runs in tomcat (8.5) as a sole web app. The total number of threads in the JVM (openjdk 1.8.0_181) increases monotonously almost (though not completely) at a constant rate, going from a few hundred in the beginning, to about 3000 in a week. By that time, the majority of the threads stack traces look like:



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)


The application works otherwise fine, these threads do not seem to take up too much memory (at least compared to the tens of gigabytes the application normally consumes), but their existence points to some hidden leak inside the application. As of writing this, I can not currently find a thread named pool-.* in a different state, so I don't know what they normally do before going zombie. The application is never redeployed without a tomcat restart.



My question would be whether anyone encountered anything similar and how they solved it, and if not, how could I diagnose why these threads are being created and not removed afterwards.










share|improve this question

























  • So you mean to say all threads are waiting and none have closed. Had it been an issue with tomcat, you would have easily found that out by now, anyways do mentioned the tomcat version you are using. Are you anywhere in your application setting up Executors, if yes. I would recommend checking that code or using the constructor that takes ThreadFactory as input. Override the newThread method in the factory to use custom names. If its your application then with the thread name you can easily figure out the faulty code and work on that particular piece.

    – Himanshu Bhardwaj
    yesterday











  • OK so it's a worker thread pool. What are the thread names?

    – Andy Brown
    yesterday











  • @AndyBrown thread names: pool-[0-9]*-thread-1,5,main

    – P.Péter
    yesterday


















1















I have a spring boot (1.5.2) web application that runs in tomcat (8.5) as a sole web app. The total number of threads in the JVM (openjdk 1.8.0_181) increases monotonously almost (though not completely) at a constant rate, going from a few hundred in the beginning, to about 3000 in a week. By that time, the majority of the threads stack traces look like:



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)


The application works otherwise fine, these threads do not seem to take up too much memory (at least compared to the tens of gigabytes the application normally consumes), but their existence points to some hidden leak inside the application. As of writing this, I can not currently find a thread named pool-.* in a different state, so I don't know what they normally do before going zombie. The application is never redeployed without a tomcat restart.



My question would be whether anyone encountered anything similar and how they solved it, and if not, how could I diagnose why these threads are being created and not removed afterwards.










share|improve this question

























  • So you mean to say all threads are waiting and none have closed. Had it been an issue with tomcat, you would have easily found that out by now, anyways do mentioned the tomcat version you are using. Are you anywhere in your application setting up Executors, if yes. I would recommend checking that code or using the constructor that takes ThreadFactory as input. Override the newThread method in the factory to use custom names. If its your application then with the thread name you can easily figure out the faulty code and work on that particular piece.

    – Himanshu Bhardwaj
    yesterday











  • OK so it's a worker thread pool. What are the thread names?

    – Andy Brown
    yesterday











  • @AndyBrown thread names: pool-[0-9]*-thread-1,5,main

    – P.Péter
    yesterday
















1












1








1








I have a spring boot (1.5.2) web application that runs in tomcat (8.5) as a sole web app. The total number of threads in the JVM (openjdk 1.8.0_181) increases monotonously almost (though not completely) at a constant rate, going from a few hundred in the beginning, to about 3000 in a week. By that time, the majority of the threads stack traces look like:



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)


The application works otherwise fine, these threads do not seem to take up too much memory (at least compared to the tens of gigabytes the application normally consumes), but their existence points to some hidden leak inside the application. As of writing this, I can not currently find a thread named pool-.* in a different state, so I don't know what they normally do before going zombie. The application is never redeployed without a tomcat restart.



My question would be whether anyone encountered anything similar and how they solved it, and if not, how could I diagnose why these threads are being created and not removed afterwards.










share|improve this question
















I have a spring boot (1.5.2) web application that runs in tomcat (8.5) as a sole web app. The total number of threads in the JVM (openjdk 1.8.0_181) increases monotonously almost (though not completely) at a constant rate, going from a few hundred in the beginning, to about 3000 in a week. By that time, the majority of the threads stack traces look like:



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)


The application works otherwise fine, these threads do not seem to take up too much memory (at least compared to the tens of gigabytes the application normally consumes), but their existence points to some hidden leak inside the application. As of writing this, I can not currently find a thread named pool-.* in a different state, so I don't know what they normally do before going zombie. The application is never redeployed without a tomcat restart.



My question would be whether anyone encountered anything similar and how they solved it, and if not, how could I diagnose why these threads are being created and not removed afterwards.







java spring tomcat threadpool






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday







P.Péter

















asked yesterday









P.PéterP.Péter

892929




892929













  • So you mean to say all threads are waiting and none have closed. Had it been an issue with tomcat, you would have easily found that out by now, anyways do mentioned the tomcat version you are using. Are you anywhere in your application setting up Executors, if yes. I would recommend checking that code or using the constructor that takes ThreadFactory as input. Override the newThread method in the factory to use custom names. If its your application then with the thread name you can easily figure out the faulty code and work on that particular piece.

    – Himanshu Bhardwaj
    yesterday











  • OK so it's a worker thread pool. What are the thread names?

    – Andy Brown
    yesterday











  • @AndyBrown thread names: pool-[0-9]*-thread-1,5,main

    – P.Péter
    yesterday





















  • So you mean to say all threads are waiting and none have closed. Had it been an issue with tomcat, you would have easily found that out by now, anyways do mentioned the tomcat version you are using. Are you anywhere in your application setting up Executors, if yes. I would recommend checking that code or using the constructor that takes ThreadFactory as input. Override the newThread method in the factory to use custom names. If its your application then with the thread name you can easily figure out the faulty code and work on that particular piece.

    – Himanshu Bhardwaj
    yesterday











  • OK so it's a worker thread pool. What are the thread names?

    – Andy Brown
    yesterday











  • @AndyBrown thread names: pool-[0-9]*-thread-1,5,main

    – P.Péter
    yesterday



















So you mean to say all threads are waiting and none have closed. Had it been an issue with tomcat, you would have easily found that out by now, anyways do mentioned the tomcat version you are using. Are you anywhere in your application setting up Executors, if yes. I would recommend checking that code or using the constructor that takes ThreadFactory as input. Override the newThread method in the factory to use custom names. If its your application then with the thread name you can easily figure out the faulty code and work on that particular piece.

– Himanshu Bhardwaj
yesterday





So you mean to say all threads are waiting and none have closed. Had it been an issue with tomcat, you would have easily found that out by now, anyways do mentioned the tomcat version you are using. Are you anywhere in your application setting up Executors, if yes. I would recommend checking that code or using the constructor that takes ThreadFactory as input. Override the newThread method in the factory to use custom names. If its your application then with the thread name you can easily figure out the faulty code and work on that particular piece.

– Himanshu Bhardwaj
yesterday













OK so it's a worker thread pool. What are the thread names?

– Andy Brown
yesterday





OK so it's a worker thread pool. What are the thread names?

– Andy Brown
yesterday













@AndyBrown thread names: pool-[0-9]*-thread-1,5,main

– P.Péter
yesterday







@AndyBrown thread names: pool-[0-9]*-thread-1,5,main

– P.Péter
yesterday














1 Answer
1






active

oldest

votes


















0














The most likely causes for threads being spawned in this fashion:




  1. Tomcat was misconfigured e.g. executor maxThreads set to unreasonably high value from default 200.

  2. Application code creates an ubound thread pool e.g. Executors.newCachedThreadPool() which experiences a thread spike.

  3. During application re-deployment the thread pool created by undeployed application is not stopped correctly. See this answer.

  4. Application code creates threads with new Thread().


Point 4 is unlikely since your stack trace is showing java.util.concurrent.ThreadPoolExecutor. Find the pool which creates threads with prefix pool- (grep application code and Tomcat configuration for pool-). Then cap the pool.






share|improve this answer



















  • 1





    Point 1 is not likely. Tomcat uses it's own TaskQueue class extending LinkedBlockingQueue and overriding take(). TaskQueue.take() would appear in the stack trace.

    – Andy Brown
    yesterday











  • Point 3 is not likely, we always restart tomcat before redeploying. I will edit the question to add additional info.

    – P.Péter
    yesterday











  • Point 1 is also not likely, as those should start with catalina-exec- as server.xml states: <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" Oh sorry, it is commented out, so could be that.

    – P.Péter
    yesterday













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54251799%2fhow-to-locate-thread-leak-in-spring-tomcat-application%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














The most likely causes for threads being spawned in this fashion:




  1. Tomcat was misconfigured e.g. executor maxThreads set to unreasonably high value from default 200.

  2. Application code creates an ubound thread pool e.g. Executors.newCachedThreadPool() which experiences a thread spike.

  3. During application re-deployment the thread pool created by undeployed application is not stopped correctly. See this answer.

  4. Application code creates threads with new Thread().


Point 4 is unlikely since your stack trace is showing java.util.concurrent.ThreadPoolExecutor. Find the pool which creates threads with prefix pool- (grep application code and Tomcat configuration for pool-). Then cap the pool.






share|improve this answer



















  • 1





    Point 1 is not likely. Tomcat uses it's own TaskQueue class extending LinkedBlockingQueue and overriding take(). TaskQueue.take() would appear in the stack trace.

    – Andy Brown
    yesterday











  • Point 3 is not likely, we always restart tomcat before redeploying. I will edit the question to add additional info.

    – P.Péter
    yesterday











  • Point 1 is also not likely, as those should start with catalina-exec- as server.xml states: <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" Oh sorry, it is commented out, so could be that.

    – P.Péter
    yesterday


















0














The most likely causes for threads being spawned in this fashion:




  1. Tomcat was misconfigured e.g. executor maxThreads set to unreasonably high value from default 200.

  2. Application code creates an ubound thread pool e.g. Executors.newCachedThreadPool() which experiences a thread spike.

  3. During application re-deployment the thread pool created by undeployed application is not stopped correctly. See this answer.

  4. Application code creates threads with new Thread().


Point 4 is unlikely since your stack trace is showing java.util.concurrent.ThreadPoolExecutor. Find the pool which creates threads with prefix pool- (grep application code and Tomcat configuration for pool-). Then cap the pool.






share|improve this answer



















  • 1





    Point 1 is not likely. Tomcat uses it's own TaskQueue class extending LinkedBlockingQueue and overriding take(). TaskQueue.take() would appear in the stack trace.

    – Andy Brown
    yesterday











  • Point 3 is not likely, we always restart tomcat before redeploying. I will edit the question to add additional info.

    – P.Péter
    yesterday











  • Point 1 is also not likely, as those should start with catalina-exec- as server.xml states: <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" Oh sorry, it is commented out, so could be that.

    – P.Péter
    yesterday
















0












0








0







The most likely causes for threads being spawned in this fashion:




  1. Tomcat was misconfigured e.g. executor maxThreads set to unreasonably high value from default 200.

  2. Application code creates an ubound thread pool e.g. Executors.newCachedThreadPool() which experiences a thread spike.

  3. During application re-deployment the thread pool created by undeployed application is not stopped correctly. See this answer.

  4. Application code creates threads with new Thread().


Point 4 is unlikely since your stack trace is showing java.util.concurrent.ThreadPoolExecutor. Find the pool which creates threads with prefix pool- (grep application code and Tomcat configuration for pool-). Then cap the pool.






share|improve this answer













The most likely causes for threads being spawned in this fashion:




  1. Tomcat was misconfigured e.g. executor maxThreads set to unreasonably high value from default 200.

  2. Application code creates an ubound thread pool e.g. Executors.newCachedThreadPool() which experiences a thread spike.

  3. During application re-deployment the thread pool created by undeployed application is not stopped correctly. See this answer.

  4. Application code creates threads with new Thread().


Point 4 is unlikely since your stack trace is showing java.util.concurrent.ThreadPoolExecutor. Find the pool which creates threads with prefix pool- (grep application code and Tomcat configuration for pool-). Then cap the pool.







share|improve this answer












share|improve this answer



share|improve this answer










answered yesterday









Karol DowbeckiKarol Dowbecki

19.6k92851




19.6k92851








  • 1





    Point 1 is not likely. Tomcat uses it's own TaskQueue class extending LinkedBlockingQueue and overriding take(). TaskQueue.take() would appear in the stack trace.

    – Andy Brown
    yesterday











  • Point 3 is not likely, we always restart tomcat before redeploying. I will edit the question to add additional info.

    – P.Péter
    yesterday











  • Point 1 is also not likely, as those should start with catalina-exec- as server.xml states: <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" Oh sorry, it is commented out, so could be that.

    – P.Péter
    yesterday
















  • 1





    Point 1 is not likely. Tomcat uses it's own TaskQueue class extending LinkedBlockingQueue and overriding take(). TaskQueue.take() would appear in the stack trace.

    – Andy Brown
    yesterday











  • Point 3 is not likely, we always restart tomcat before redeploying. I will edit the question to add additional info.

    – P.Péter
    yesterday











  • Point 1 is also not likely, as those should start with catalina-exec- as server.xml states: <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" Oh sorry, it is commented out, so could be that.

    – P.Péter
    yesterday










1




1





Point 1 is not likely. Tomcat uses it's own TaskQueue class extending LinkedBlockingQueue and overriding take(). TaskQueue.take() would appear in the stack trace.

– Andy Brown
yesterday





Point 1 is not likely. Tomcat uses it's own TaskQueue class extending LinkedBlockingQueue and overriding take(). TaskQueue.take() would appear in the stack trace.

– Andy Brown
yesterday













Point 3 is not likely, we always restart tomcat before redeploying. I will edit the question to add additional info.

– P.Péter
yesterday





Point 3 is not likely, we always restart tomcat before redeploying. I will edit the question to add additional info.

– P.Péter
yesterday













Point 1 is also not likely, as those should start with catalina-exec- as server.xml states: <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" Oh sorry, it is commented out, so could be that.

– P.Péter
yesterday







Point 1 is also not likely, as those should start with catalina-exec- as server.xml states: <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" Oh sorry, it is commented out, so could be that.

– P.Péter
yesterday




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54251799%2fhow-to-locate-thread-leak-in-spring-tomcat-application%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Liquibase includeAll doesn't find base path

How to use setInterval in EJS file?

Petrus Granier-Deferre