在运行的JVM中查找正在运行的实例

4
我想知道是否有可能掌握给定类的运行实例。触发这个问题的特定问题是一个应用程序由于许多运行中的线程而无法正常退出。
是的,我知道你可以将线程设为守护进程,然后它们就不会阻止应用程序退出。但这确实让我想知道是否可能。我能找到的最接近的东西是类加载器(受保护!)findLoadedClass,尽管您必须通过自己的类加载器来运行它。
在相关说明上,这是分析工具如何跟踪对象句柄的方式吗?通过运行它们自己的自定义类加载器吗?还是有一些我没有看到的好方法?
5个回答

5
你确实可以在类 Unix 的操作系统上使用kill -QUIT <pid> 或在 Windows 控制台中运行应用程序并按Ctrl-Pause来将所有正在运行的线程堆栈跟踪转储到标准输出。 然而,看起来你想要编程的方法。所以,假设你真正想要的是当前调用堆栈包含给定类中一个或多个方法的所有线程集合...最好的方法是检查所有运行线程的堆栈。我没有尝试过这种方法,但它应该适用于Java 1.5及更高版本。请记住,根据定义,这完全不是线程安全的(运行线程列表和它们当前的堆栈跟踪将在你的下面不断发生变化......需要进行大量谨慎的处理才能真正利用这个列表)。
public Set<Thread> findThreadsRunningClass(Class classToFindRunning) {

  Set<Thread> runningThreads = new HashSet<Thread>();
  String className = classToFindRunning.getName();

  Map<Thread,StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
  for(Thread t : stackTraces.keySey()) {
    StackTraceElement[] steArray = stackTraces.get(t);
    for(int i = 0;i<steArray.size();i++) {
      StackTraceElement ste = steArray[i];
      if(ste.getClassName().equals(className)) {
        runningThreads.add(t);
        continue;
      }
    }
  }

  return runningThreads;
}

如果这种方法适合您,请告诉我!


3
这个页面得知,Java分析器使用本地接口与JVM(对于Java <=1.4.2使用JVMPI,对于Java >=1.5.0使用JVMTI)交互,以从正在运行的Java应用程序中获取分析信息。这意味着一些由Sun提供的本机代码为分析器提供了在JVM中的钩子。

2

如果您只需要快速获取运行中应用程序的堆栈跟踪,以查找哪些线程正在阻止JVM退出,您可以向其发送QUIT信号。

$ kill -QUIT <pid of java process>

在Windows操作系统下,您需要在控制台窗口中运行应用程序(使用java.exe而不是javaw.exe),然后可以按Ctrl-Pause键生成堆栈转储。在这两种情况下,它都会被写入标准输出。

1

我使用Visual VM来监控JVM。它有很多功能,你可以试试。


0

我认为你需要一个Java线程转储。这应该列出所有线程以及它们当前正在做什么。我自己曾经遇到过类似的问题,使用线程转储帮助解决了问题(Quartz调度程序线程,在Tomcat完成后没有退出)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接