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

android - Gradle sync Error:Configuration with name 'default' not found -

java - Andrioid studio start fail: Fatal error initializing 'null' -

html - jQuery UI Sortable - Remove placeholder after item is dropped -