7

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

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

还是有更好的方法来做到这一点?

4

5 回答 5

10

作为一个快速破解,这比我想象的容易得多。由于这是一个快速的 hack,我没有做一些事情,比如在取消引用数组之前确保堆栈跟踪足够深等。我在我签名的 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().

于 2009-04-28T20:19:19.503 回答
4

在尝试任何过于疯狂的事情之前,您是否考虑过使用Java 调试 API?我认为在 Thread.interrupt() 上捕获 MethodEntryEvents 就可以了。

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

于 2009-04-28T17:29:44.000 回答
2

我会看看AspectJ及其包装方法调用的能力。围绕该方法的执行切入点interrupt()在这里应该有所帮助。

请注意,由于您希望拦截 Java 系统方法调用(而不是您的应用程序代码),因此上述方法可能不适合。该线程似乎表明这是可能的,但请注意他创建了一个编织的rt.jar。

于 2009-04-28T17:31:09.707 回答
1

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

两者都需要一些时间来学习,但是使用起来很有趣,一旦掌握了它,您就可以在未来将它们用于各种有趣的事情:-) 我真的没有任何好的片段可以粘贴在这里现在,但如果你在谷歌上搜索 ASM,也许看看 JIP 以了解 ASM 的一些创造性使用,我想你会找到灵感的。

JIP:Java 交互式探查器

于 2009-04-28T17:53:20.527 回答
0

您也可以尝试使用 JMX:

ManagementFactory.getThreadMXBean().getThreadInfo(aThreadID)

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

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

编辑

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

long[] ids = ManagementFactory.getThreadMXBean().getAllThreadIds();
于 2009-04-28T17:39:53.833 回答