在Java中有没有办法记录*每个* Thread中断?

时间:2009-04-28 17:25:45

标签: java multithreading debugging interrupt

我想以某种方式记录每次调用Thread.interrupt()时,记录哪个线程发出了调用(及其当前堆栈)以及识别有关哪个线程被中断的信息。

有办法做到这一点吗?在搜索信息时,我看到有人提到了实施安全管理器的可能性。这是可以在运行时完成的事情(例如,在Applet或Web Start客户端中),还是需要使用已安装的JVM来实现此目的?

或者有更好的方法吗?

5 个答案:

答案 0 :(得分:10)

作为一个快速的黑客,这比我想象的更容易做到很多。由于这是一个快速入侵,我没有做任何事情,比如在取消引用数组之前确保堆栈跟踪足够深,等等。我在我签名的Applet的构造函数中插入了以下内容:

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);
      }
    });

dumpThreadStack方法如下:

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());
}

当然,我永远不会把它留在生产代码中,但它足以让我确切地告诉我哪个线程导致interrupt()我没想到。也就是说,使用此代码,我会在每次调用Thread.interrupt()时获得堆栈转储。

答案 1 :(得分:4)

在尝试过于狂野之前,您是否考虑过使用Java debugging API?我认为在Thread.interrupt()上捕获MethodEntryEvents会做到这一点。

Eeek,这是旧界面,您还应该检查新的JVM Tool Interface

答案 2 :(得分:2)

我会查看AspectJ及其包装方法调用的功能。 interrupt()方法周围的execution pointcut应该有帮助。

请注意,由于您正在寻找拦截Java系统方法调用(而不是您的应用程序代码),因此上述可能不适合。 This thread似乎暗示它是可能的,但请注意他创建了一个编织 rt.jar。

答案 3 :(得分:1)

正如其他人所说的......如果它是一次性的事情,JVMTI可能是最核心的方式。但是,同样有趣的是使用asm库和instrumentation API来创建一个代理,该代理插入对在Thread.interrupt()调用之前创建的静态方法的调用(或者可能改变Thread.interrupt( )做同样的方法,我想你可以这样做。)

两者都需要一些时间来学习,但是使用起来非常有趣,一旦掌握了它,你可以将它们用于各种有趣的事情:-) 我现在没有任何好的片段可以粘贴到这里但是如果你围绕ASM进行搜索并且可能会看到JIP对ASM的一些创造性使用我认为你会找到灵感。

JIP:Java Interactive Profiler

答案 4 :(得分:0)

您也可以尝试使用JMX:

ManagementFactory.getThreadMXBean().getThreadInfo(aThreadID)

使用您可以记录的ThreadInfo对象:

  • 线程的堆栈跟踪
  • 一般用户信息,如姓名,状态等

修改

使用getAllThreadIds()以获取活动线程ID列表:

long[] ids = ManagementFactory.getThreadMXBean().getAllThreadIds();