9

in tomcat,if a webapp did stop a none daemon thread,tomcat can not be shutdown by shutdown.sh

for example:

public class demo implements ServletContextListener{

  public void contextDestroyed(ServletContextEvent arg0) {
    // TODO Auto-generated method stub
    // yes,we can cancel timer in here,but this is not the major problem
   }

  public void contextInitialized(ServletContextEvent arg0) {        
    Timer timer = new Timer();
    timer.schedule(new Test(), 1000, 1000*10);
    }
}

public class Test extends TimerTask{  
@Override
public void run() {
    System.out.println("AAAA");        
   }
}

like as above,tomcat can not be shutdown by shutdown.sh. from jvisualvm,threads inspector say:

"Timer-0" - Thread t@40
   java.lang.Thread.State: TIMED_WAITING
    at java.lang.Object.wait(Native Method)
    - waiting on <3957edeb> (a java.util.TaskQueue)
    at java.util.TimerThread.mainLoop(Timer.java:552)
    at java.util.TimerThread.run(Timer.java:505)

   Locked ownable synchronizers:
    - None

stack info did not point out which java class created the thread, my question is how to find out who created the thread from many webapps.

Thanks!

jenlin
  • 93
  • 1
  • 4

4 Answers4

25

Here is the list of approaches, sorted from quickest / most reliable to slowest / hardest:

  1. If you have the source of the class, create an exception in the constructor (without actually throwing it). You can simply examine or print it when you need to know when the thread was created.

  2. If you don't have the sources, the thread name can be a good hint who created it.

  3. If the name hints to a generic service (like java.util.Timer), then you can create a conditional breakpoint in your IDE in the constructor. The condition should be the thread name; the debugger will then stop when someone creates a thread with this name.

  4. If you don't have too many threads, set a breakpoint in the constructors of Thread.

  5. If you have many threads, attach a debugger to the app and freeze it. Then examine the stack traces.

  6. If everything else fails, get the source code for the Java runtime and add logging code in the classes you want to observe, compile a new rt.jar and replace the original one with your version. Don't try this in production, please.

  7. If money isn't an issue, you can use dynamic tracing tools like Compuware APM or, if you're on Linux or Solaris, you can try SystemTap and dtrace, respectively.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Thanks @Aaron Digulla very much so good and detail. in this case,we can only get stack info just like above so i tried to use btrace for get more detail,unfortunate i got nothing helpful info yet. anyway,thanks Aaron Digulla,your reply contains a lot of useful information. – jenlin Sep 25 '13 at 08:58
  • Thank you @Aaron Digulla . your 4th and 5th point saved me a week effort. Attached debug points to Thread Constructor and debugged to find out who created the thread which was causing issue in my application. – DecKno Jan 20 '16 at 06:35
2

If you have control of the class you can catch the stack trace when it is created:

public class Test extends TimerTask {
  final StackTraceElement[] callerStack;

  public Test () {
    callerStack = Thread.currentThread().getStackTrace();
  }

  @Override
  public void run() {
    System.out.println("AAAA");
    System.out.println("Creator: "+Arrays.asList(callerStack));
  }

  @Override
  public String toString () {
    return "Test created by "+Arrays.asList(callerStack);
  }
}
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • sorry,in some case,we can not control source,and we even did not which thread or class lead to tomcat shutdown fail. so,my question is how to find out the thread or class,so that we can notify the code owner. – jenlin Sep 25 '13 at 08:14
2

You can also write a tiny java Instrumentation agent to wrap the thread constructor (and stack dump there), instead of trying to mod the rt.jar classes.

user2023577
  • 1,752
  • 1
  • 12
  • 23
0

If you have an IDE like Eclipse or Intellij, you can set break points in the various Thread constructors. You can remotely attach to process using the debugger. The debugger will stop the process when the thread is being constructed. You can observe things like the thread name. You can also use break points with condition if you want to match on the specific thread name.

Setting break points. https://www.ibm.com/developerworks/library/os-ecbug/

Remote debugging https://dzone.com/articles/a-practical-guide-to-java-remote-debugging-in-the

micbster
  • 51
  • 1
  • 3