Question

I would like to somehow log every time Thread.interrupt() is called, logging which Thread issued the call (and its current stack) as well as identifying information about which Thread is being interrupted.

Is there a way to do this? Searching for information, I saw someone reference the possibility of implementing a security manager. Is this something that can be done at runtime (e.g., in an Applet or Web Start client), or do you need to tool the installed JVM to do this?

Or is there a better way to do this?

Was it helpful?

Solution

As a quick hack, this was a lot easier to do than I thought it would be. Since this is a quick hack, I didn't do things like ensure that the stack trace is deep enough before dereferencing the array, etc. I inserted the following in my signed Applet's constructor:

log.info("Old security manager = " + System.getSecurityManager());
System.setSecurityManager(new SecurityManager() {
      @Override
      public void checkAccess(final Thread t) {
        StackTraceElement[] list = Thread.currentThread().getStackTrace();
        StackTraceElement element = list[3];
        if (element.getMethodName().equals("interrupt")) {
          log.info("CheckAccess to interrupt(Thread = " + t.getName() + ") - "
                   + element.getMethodName());
          dumpThreadStack(Thread.currentThread());
        }
        super.checkAccess(t);
      }
    });

and the dumpThreadStack method is as follows:

public static void dumpThreadStack(final Thread thread) {
  StringBuilder builder = new StringBuilder('\n');
  try {
    for (StackTraceElement element : thread.getStackTrace()) {
      builder.append(element.toString()).append('\n');
    }
  } catch (SecurityException e) { /* ignore */ }
  log.info(builder.toString());
}

I could never, of course, leave this in production code, but it sufficed to tell me exactly which thread was causing an interrupt() that I didn't expect. That is, with this code in place, I get a stack dump for every call to Thread.interrupt().

OTHER TIPS

Before trying anything too wild, have you considered using the Java debugging API? I'd think that capturing MethodEntryEvents on Thread.interrupt() would do it.

Eeek, that's the old interface, you should also check oout the new JVM Tool Interface.

I would look at AspectJ and its capabilities to wrap method calls. An execution pointcut around the interrupt() method should help here.

Note that since you're looking to intercept a Java system method call (as opposed to your application code), the above may not be suitable. This thread seems to suggest it's possible, but note that he's created a woven rt.jar.

As others have said... If it is a one-time thing JVMTI is probably the most hardcore way to go. However, just as fun could be to use the asm library and the instrumentation APIs to create an agent that inserts a call to a static method you've created just before the Thread.interrupt() call (or maybe alters the Thread.interrupt() method to do the same, I think you can do that).

Both takes some time to learn but it is quite fun to work with and once you get the hold of it you can use them for all kinds of funny things in the future :-) I don't really have any good snippets to paste here right now but if you google around for ASM and maybe look at the JIP for some creative use of ASM I think you will find inspiration.

JIP: Java Interactive Profiler

You could try also with JMX:

ManagementFactory.getThreadMXBean().getThreadInfo(aThreadID)

with the ThreadInfo object you can log:

  • the stack trace of the thread
  • general userful information like name, status, etc
  • etc

EDIT

use getAllThreadIds() in order to obtain the list of live thread ids:

long[] ids = ManagementFactory.getThreadMXBean().getAllThreadIds();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top