Is there any way in Java to log *every* Thread interrupt?

前端 未结 5 800
清酒与你
清酒与你 2021-02-06 12:11

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

相关标签:
5条回答
  • 2021-02-06 12:46

    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.

    0 讨论(0)
  • 2021-02-06 12:51

    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();
    
    0 讨论(0)
  • 2021-02-06 12:53

    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

    0 讨论(0)
  • 2021-02-06 12:56

    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.

    0 讨论(0)
  • 2021-02-06 13:01

    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().

    0 讨论(0)
提交回复
热议问题