Мониторинг Java изнутри Java - PullRequest
1 голос
/ 24 октября 2009

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

Что мне нужно, так это возможность наблюдать методы, которые вызывает программа, и какие методы вызываются в этом методе и так далее. Очевидно, трассировки стека обеспечивают именно эту функциональность:

 java.lang.NullPointerException
     at MyClass.mash(MyClass.java:9)
     at MyClass.crunch(MyClass.java:6)
     at MyClass.main(MyClass.java:3)

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

Теперь я, конечно, подумал о том, чтобы просто изменить PrintStream класса System, чтобы поток печатал свой стек в my PrintStream, но это выглядит как-то неправильно.

Есть ли лучший способ сделать это? Существуют ли какие-либо ранее существующие классы / методы, которые я могу использовать?

Кроме того, в настоящее время я загружаю исходный код Java, чтобы проверить, как именно класс потока печатает свой стек, чтобы я мог, возможно, создать подкласс потока и имитировать метод dumpStack () с помощью моего собственного метода getStack ().

Ответы [ 5 ]

2 голосов
/ 24 октября 2009

Посмотрите также на VisualVM, поставляемый с последними выпусками Java.

1 голос
/ 24 октября 2009

Ой, просматривая исходный код, я заметил, что у класса потока есть метод public StackTraceElement [] getStackTrace (), его просто нет в документации, которую я читал. Теперь я чувствую себя глупо.

Так что да, похоже, это решение.

0 голосов
/ 24 октября 2009

Посмотрите на класс ThreadMXBean - он может предоставить то, что вам нужно. По сути, вы:

  • вызовите ManagementFactory.getThreadMXBean (), чтобы получить экземпляр ThreadMXBean;
  • вызовите getAllThreadIds () для результирующего ThreadMXBean для перечисления текущих потоков;
  • вызовите getThreadInfo (), чтобы получить первые n элементов трассировки стека из заданного списка потоков.
0 голосов
/ 24 октября 2009

Вы можете использовать AspectJ для этого. Посмотрите на это описание именно вашего варианта использования.

0 голосов
/ 24 октября 2009

Один из подходов может заключаться в использовании чего-то вроде BCEL для предварительной обработки целевого байт-кода для вставки вызовов в ваш собственный код при каждом входе и выходе метода (вероятно, лучше всего выполнить выход, обернув весь метод в попытку / Блок наконец, чтобы поймать выходы исключения). Отсюда вы можете вывести дерево вызовов именно так, как оно происходит.

...