java - How to get rid of tomcat memory leak log entries caused by a sleeping thread -


any idea how can rid of following tomcat log entries:

severe: web application [/my-app] appears have started thread named [thread-11] has failed stop it. create memory leak. jun 29, 2015 11:14:33 org.apache.catalina.loader.webappclassloader clearreferencesthreads 

i'm getting them while shutting down tomcat 7.0.42.

the thread dump looks this:

"thread-11" daemon prio=10 tid=0x00007fedc0bd5000 nid=0x2983 waiting on condition [0x00007fedbacef000]    java.lang.thread.state: timed_waiting (sleeping)     @ java.lang.thread.sleep(native method)     @ com.my.app.test$workerthread.run(test.java:248) 

where java line 248 is: sleep(1000*60*pollintervalminutes);

  public void start() {      workerthread t= new workerthread(this);     t.setdaemon(true);     t.start(); } private class workerthread extends thread     {         controller controller=null;         int pollintervalminutes=0;         private boolean alive = true;          public workerthread(controller controller)         {             this.controller=controller;             pollintervalminutes=60;         }          @override         public void run()         {             while(alive)             {                 try                 {                     sleep(1000*60*pollintervalminutes);                     controller.createallprojectsifneeded();                 }                 catch (exception e)                 {                     alive = false;                 }             }         }     } 

thanks

problem seems tomcat doesn't try , stop non-managed threads created application.

looking implementation of org.apache.catalina.loader.webappclassloader clearreferencesthreads reports error, jvm threads skipped cleanup procedure.

due this, interruptedexception never thrown , therefore alive not set false, perhaps expected.

 @suppresswarnings("deprecation")     private void clearreferencesthreads() {         thread[] threads = getthreads();      // iterate on set of threads     (thread thread : threads) {         if (thread != null) {             classloader ccl = thread.getcontextclassloader();             if (ccl == this) {                 // don't warn thread                 if (thread == thread.currentthread()) {                     continue;                 }                  // jvm controlled threads                 threadgroup tg = thread.getthreadgroup();                 if (tg != null &&                         jvm_thread_group_names.contains(tg.getname())) {                      // httpclient keep-alive threads                     if (clearreferenceshttpclientkeepalivethread &&                             thread.getname().equals("keep-alive-timer")) {                         thread.setcontextclassloader(parent);                         log.debug(sm.getstring(                                 "webappclassloader.checkthreadshttpclient"));                     }                      // don't warn remaining jvm controlled threads                     continue;                 }                  // skip threads have died                 if (!thread.isalive()) {                     continue;                 }                  // timerthread can stopped safely treat separately                 if (thread.getclass().getname().equals(                         "java.util.timerthread") &&                         clearreferencesstoptimerthreads) {                     clearreferencesstoptimerthread(thread);                     continue;                 }                  if (isrequestthread(thread)) {                     log.error(sm.getstring("webappclassloader.warnrequestthread",                             contextname, thread.getname()));                 } else {                     log.error(sm.getstring("webappclassloader.warnthread",                             contextname, thread.getname()));                 }                  // don't try stop threads unless explicitly                 // configured                 if (!clearreferencesstopthreads) {                     continue;                 }                  // if thread has been started via executor, try                 // shutting down executor                 try {                     field targetfield =                         thread.getclass().getdeclaredfield("target");                     targetfield.setaccessible(true);                     object target = targetfield.get(thread);                      if (target != null &&                             target.getclass().getcanonicalname().equals(                             "java.util.concurrent.threadpoolexecutor.worker")) {                         field executorfield =                             target.getclass().getdeclaredfield("this$0");                         executorfield.setaccessible(true);                         object executor = executorfield.get(target);                         if (executor instanceof threadpoolexecutor) {                             ((threadpoolexecutor) executor).shutdownnow();                         }                     }                 } catch (securityexception e) {                     log.warn(sm.getstring(                             "webappclassloader.stopthreadfail",                             thread.getname(), contextname), e);                 } catch (nosuchfieldexception e) {                     log.warn(sm.getstring(                             "webappclassloader.stopthreadfail",                             thread.getname(), contextname), e);                 } catch (illegalargumentexception e) {                     log.warn(sm.getstring(                             "webappclassloader.stopthreadfail",                             thread.getname(), contextname), e);                 } catch (illegalaccessexception e) {                     log.warn(sm.getstring(                             "webappclassloader.stopthreadfail",                             thread.getname(), contextname), e);                 }                  // method deprecated , reason.                 // risky code option @ point.                 // *very* reason apps clean-up                 // themselves.                 thread.stop();             }         }     } } 

there 3 options can think of how avoid memory leak:

  • provide shutdown hook thread knows spawned threads , can interrupt them

how add shutdown hook

  • do not spawn threads spin endlessly in while loop can stop when finished processing
  • wrap threads in executorservice , call shutdownnow() upon application shutdown event.

    this can achieved service class annotated @weblistener , calling shutdownnow() in method:contextdestroyed(servletcontextevent event).

shutdownnow()

attempts stop actively executing tasks, halts processing of waiting tasks, , returns list of tasks awaiting execution. method not wait actively executing tasks terminate. use awaittermination that.

there no guarantees beyond best-effort attempts stop processing actively executing tasks. example, typical implementations cancel via thread.interrupt(), task fails respond interrupts may never terminate.


Comments

Popular posts from this blog

how to do line continuation in perl debugger for entering raw multi-line text (EOT)? -

javascript - Create websocket without connecting -

android - Linear layout children not scrolling -