15

Apache Tomcat says many times:

The web application [/MyServlet] appears to have started a thread named [pool-61-thread-2] but has failed to stop it. This is very likely to create a memory leak.

Is this dangerous? The servlet should be able to handle 10.000requests/day. How to close the threads when they have finished?

class Worker {

        private final CountDownLatch startSignal;
        private final CountDownLatch doneSignal;
        private final int threadNumber;

        Worker(
                CountDownLatch startSignal,
                CountDownLatch doneSignal,
                int threadNumber
        ){

            this.startSignal = startSignal;
            this.doneSignal = doneSignal;
            this.threadNumber = threadNumber;

        }

        public String[][] getSomeStrArrArr() {

            String[][] isRs = new String[8][20];
            String[][] inRs = new String[8][20];
            String[][] iwRs = new String[8][20];

            try {

                startSignal.await();

                if (threadNumber == 1) {
                    // get String[][] result for thread number 1
                    isRs = getIS(erg1, erg2, request);

                }

                if (threadNumber == 2) {
                    // get String[][] result for thread number 2
                    inRs = getIN(search_plz, request);
                }

                if (threadNumber == 3) {
                    // get String[][] result for thread number 3
                    iwRs = getIW(erg1, erg2, request);
                }

                doneSignal.countDown();

            } catch (InterruptedException ex) {

                System.out.println(
                        "Thread number "+threadNumber+" has been interrupted."
                );

            }
            if (threadNumber == 1) {
                return isRs;
            }
            if (threadNumber == 2) {
                return inRs;
            }
            if (threadNumber == 3) {
                return iwRs;
            }
            return null;
        }


        public Callable<String[][]> getSomeCallableStrArrArr(){
            return new Callable<String[][]>() {
                public String[][] call() throws Exception {
                    return getSomeStrArrArr();
                }
            };
        }

    }

    ExecutorService pool = Executors.newFixedThreadPool(3);
    Set<Future<String[][]>> set = new HashSet<Future<String[][]>>();
    CountDownLatch startSignal = new CountDownLatch(1);
    CountDownLatch doneSignal = new CountDownLatch(3);
    for (int i=1;i<=3;i++) {
        Worker worker = new Worker(startSignal,doneSignal,i);
        Callable<String[][]> callable =
                worker.getSomeCallableStrArrArr();
        Future<String[][]> future = pool.submit(callable);
        set.add(future);
    }
    startSignal.countDown();
    try {
        doneSignal.await();
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
user3876178
  • 241
  • 1
  • 4
  • 11
  • 1
    Usually you should not initialize new threads in a multi threaded environment, instead let the application server handle them unless you know what you're doing. We would need more info to get a better understanding of your problem, or use a profiler like Eclipse Memory Analyzer to check where the memory leak resides. – Luiggi Mendoza Aug 04 '14 at 20:32
  • Clean redeployment is a very fragile thing in Tomcat (and not just Tomcat). Restarting the server is often inevitable, and then the leaks are not an issue. – William F. Jameson Aug 04 '14 at 21:14
  • Sry, what do you mean by that and how to avoid that? – user3876178 Aug 04 '14 at 23:08

1 Answers1

18

Yes, it's a problem. If your code starts non-daemon threads then those threads will continue working until they exit their run method. Even if everything else finishes, the old JVM will hang around while those threads continue on. If you start up a new instance then you can have a situation where the old threads are still working alongside the ones created by the new instance.

The tasks need to be designed so that they will be responsive to interruption (as opposed to eating the exception and going on, which is what your example shows). That means checking the interrupted flag on the current thread, and catching InterruptedException in a helpful way that allows the task to break its work off and also resets the interrupted flag if needed. ExecutorService implementations have a shutdownNow method that will interrupt the current tasks.

Here's an example of how to stop a thread using interruption.

Make sure the executor gets shut down, you can handle this in a ServletContextListener.

Community
  • 1
  • 1
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • In my case the threads are from callable, not runnable because i need i return from every thread. Will this work too with interrupt? I need the return back and dont know, when the thread will exactely return... – user3876178 Aug 04 '14 at 20:49
  • @user3876178: your example is incomplete, are you doing anything to shutdown your pool currently? – Nathan Hughes Aug 04 '14 at 20:52
  • @user3876178: ExecutorService.shutdownNow. it helps if the tasks respond to interruption. – Nathan Hughes Aug 04 '14 at 20:59
  • simple but it works! i hope i works but i didnt get any error anymore. Thanks! Do you know something about this: "The web application [/MyServlet] appears to have started a thread named [MySQL Statement Cancellation Timer] but has failed to stop it. This is very likely to create a memory leak." I just have some normal mysql calls, nothing special... – user3876178 Aug 04 '14 at 21:10
  • Thx Nathan, i had the old 5.0.8 mysql connector. Updated to the newest and problem/bug solved! – user3876178 Aug 06 '14 at 17:25
  • I am having memory leak due to quartz worker.How to stop all the conection and quartz thread in jvm .I have my issue in following url.http://stackoverflow.com/questions/39166512/memory-leak-error-in-tomcat-server-even-after-removed-quartz-related-code – Vicky Aug 27 '16 at 05:45