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

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

或者有更好的方法来做到这一点吗?

有帮助吗?

解决方案

作为一个快速的黑客,这是一个的很多的容易做的比我想象的那样。由于这是一个快速的黑客,我没有做这样的事情确保堆栈跟踪足够深,我插入提领该阵列等之前在我签名的小的构造函数如下:

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()堆栈转储。

其他提示

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

哎呀,那是旧界面,你也应该看看新的 虚拟机工具 界面.

我想看看 AspectJ的和它的能力来包装方法调用。一个执行切入点各地该方法interrupt()应该帮助这里。

注意,因为你正在寻找拦截Java系统方法调用(而不是应用程序代码),上述的可能的不适合。 此线程似乎表明这是可能的,但要注意他的创建 rt.jar中。

正如其他人所说...如果这是一个一次性的事情JVMTI可能是走得最铁杆的方式。然而,一样的乐趣可能是使用ASM库和仪表API创建插入到你只是了Thread.interrupt()调用之前已经创建了一个静态方法调用代理(或可能改变了Thread.interrupt( )方法做同样的,我认为你可以做到这一点)。

这两个需要一些时间来学习,但它是相当有趣的共事者,一旦你得到它的抱着你可以在将来:-)将它们用于各种有趣的事情 我真的没有什么好的片段,现在在这里贴,但如果你谷歌周围ASM,也许看JIP一些创造性的使用ASM的我想你会找到灵感。

JIP:爪哇交互式探查

你可以尝试还有JMS:

ManagementFactory.getThreadMXBean().getThreadInfo(aThreadID)

ThreadInfo 对象,你可以登录:

  • 堆跟踪的线
  • 挖掘出来的一般信息如姓名、地位,等等
  • 等等

编辑

使用getAllThreadIds()为了获得该名单的生活thread id:

long[] ids = ManagementFactory.getThreadMXBean().getAllThreadIds();
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top