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

时间:2009-01-07 18:22:06

标签: java jvm classloader

我想知道是否可以获得运行给定类的实例的句柄。触发此问题的特定问题是由于许多正在运行的线程而无法正常退出的应用程序。

是的,我知道你可以守护theads,然后他们不会阻止应用程序退出。但它确实让我想知道这是否可行。我最接近的是类加载器(受保护!)findLoadedClass,尽管你必须通过自己的类加载器来执行此操作。

在相关的说明中,分析工具如何管理跟踪对象句柄?通过运行自己的自定义类加载器?还是有一些我看不到的好看的狡猾方式?

5 个答案:

答案 0 :(得分:5)

您确实可以通过在类似操作系统的* NIX上使用kill -QUIT <pid>,或者在Windows控制台中运行应用程序并按Ctrl-Pause(如同)来获取转储到stdout的所有正在运行的线程的堆栈跟踪另一张海报说明。)

但是,您似乎要求以编程方式执行此操作。因此,假设您真正想要的是当前调用堆栈的所有线程的集合包括来自给定类的一个或多个方法......

我能找到的最好的事情是不涉及对JVMTI的调用是检查所有正在运行的线程的堆栈。我没有试过这个,但它应该在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;
}

请告诉我这种方法是否适用于您!

答案 1 :(得分:3)

来自this page

  

Java探查器使用JVM的本机接口(JVMPI for Java&lt; = 1.4.2或JVMTI for Java >=1.5.0)从正在运行的Java应用程序获取分析信息。

这相当于一些Sun supplied native code,它将探查器挂钩到JVM中。

答案 2 :(得分:2)

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

$ kill -QUIT <pid of java process>

在Windows下,您需要在控制台窗口中运行应用程序(使用java.exe,而不是javaw.exe),然后按Ctrl-Pause生成堆栈转储。在这两种情况下都写入stdout。

答案 3 :(得分:1)

我使用Visual VM来监视JVM。有很多功能,试一试。

答案 4 :(得分:0)

我认为你需要一个Java thread dump。这应该列出所有线程与他们目前正在做的事情。我自己也有类似的问题,一个线程转储帮助解决了(Quartz调度程序线程,当Tomcat完成时没有退出)。