Поиск запущенных экземпляров в работающей JVM - PullRequest
4 голосов
/ 07 января 2009

Мне интересно, возможно ли получить хэндл для запуска экземпляров данного класса. Особая проблема, которая вызвала это, была приложением, которое не выходит красиво из-за множества работающих потоков.

Да, я знаю, что вы можете демонизировать theads, и они не будут задерживать выход из приложения. Но это заставило меня задуматься, возможно ли это. Самое близкое, что я могу, это загрузчики классов (защищены!) findLoadedClass , хотя для этого вам нужно будет запустить свой собственный загрузчик классов.

В связанной заметке, как инструментам профилирования удается отслеживать дескрипторы объектов? запустив свои собственные загрузчики классов? или есть какой-то хороший хитрый способ, которого я не вижу?

Ответы [ 5 ]

5 голосов
/ 08 января 2009

Вы действительно можете получить трассировку стека всех запущенных потоков, выгруженных в стандартный вывод, используя kill -QUIT <pid> в * NIX-подобной ОС или запустив приложение в консоли Windows и нажав Ctrl-Pause (как отмечает другой участник). )

Тем не менее, похоже, что вы запрашиваете программные способы сделать это. Итак, если вы действительно хотите, чтобы набор всех потоков, в которые текущие стеки вызовов включены один или несколько методов из данного класса ...

Лучшее, что я могу найти, если не задействовать вызовы в 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;
}

Дайте мне знать, если этот подход сработает для вас!

3 голосов
/ 07 января 2009

С этой страницы ,

Профилировщик Java использует собственный интерфейс для JVM (JVMPI для Java <= 1.4.2 или <a href="http://en.wikipedia.org/wiki/Java_Virtual_Machine_Tools_Interface" rel="nofollow noreferrer"> JVMTI для Java> = 1.5.0 ) для получения информации о профилировании из работающего приложения Java.

Это равняется некоторому предоставленному Sun исходному коду , который позволяет подключать профилировщик к JVM.

2 голосов
/ 07 января 2009

Если вам нужно только быстрое отслеживание стека вашего работающего приложения, чтобы выяснить, какие потоки блокируют выход JVM, вы можете отправить ему сигнал QUIT.

$ kill -QUIT <pid of java process>

В Windows вам нужно запустить приложение в окне консоли (используя java.exe, а не javaw.exe), затем вы можете нажать Ctrl-Pause, чтобы сгенерировать дамп стека. В обоих случаях это записано на стандартный вывод.

1 голос
/ 07 января 2009

Я использую Visual VM для мониторинга JVM. Имеет множество функций, попробуйте.

0 голосов
/ 07 января 2009

Я думаю, вам нужен дамп Java-потока . Это должно перечислить все темы с тем, что они делают в данный момент. У меня была похожая проблема, которую помог решить дамп потока (потоки планировщика Quartz, который не завершился после завершения работы Tomcat).

...