Monitoramento Java de dentro de Java
-
06-07-2019 - |
Pergunta
Eu quero escrever um simples visualização de um programa Java, exibindo chamadas de método do programa como galhos de uma árvore. Isso poderia ser feito muito simplesmente por ter o programa em si contar a visualização o que está fazendo, mas eu quero ser capaz de fazer isso com qualquer Java método / classe e não apenas aqueles que modificam a fazê-lo.
O que eu preciso é a capacidade de assistir os métodos de um programa chama e que métodos são chamados dentro desse método e assim por diante. Obviamente, os rastreamentos de pilha fornecer exatamente essa funcionalidade:
java.lang.NullPointerException
at MyClass.mash(MyClass.java:9)
at MyClass.crunch(MyClass.java:6)
at MyClass.main(MyClass.java:3)
Então eu pensei em ter o programa que eu quero para monitorar execução em um fio e, em seguida, basta olhar para pilha que thread. No entanto, a classe thread não realmente apoiar esta. Ele suporta apenas imprimir a pilha atual.
Agora eu, é claro, pensou em simplesmente mudando a PrintStream da classe do sistema para o segmento iria imprimir sua pilha em minha PrintStream, mas este se sente tipo de errado.
Existe uma maneira melhor de fazer isso? Há algum pré-existentes classes / métodos posso usar?
Além disso, estou atualmente transferir o código fonte Java, para verificar como exatamente a classe Thread imprime sua pilha para que eu pudesse fio talvez subclasse e imitar o método dumpStack () com o meu próprio método getStack ().
Solução 2
Oh disparar, olhando através do código fonte notei a classe thread tem um método público StackTraceElement [] getStackTrace (), ele simplesmente não estava na documentação que estava lendo. Agora me sinto idiota.
Então, sim, que parece ser a solução.
Outras dicas
Veja também a VisualVM, fornecido com versões mais recentes de Java.
Uma abordagem seria usar algo como bytecode BCEL para pré-processar o alvo para inserir chamadas para seu próprio código em cada entrada método e saída (provavelmente melhor para fazer sair envolvendo o método inteiro em um try / finally bloco, às saídas de exceção captura). A partir daí, você pode deduzir a árvore de chamadas exatamente como isso acontece.
Tenha um olhar para o ThreadMXBean classe - é o meu fornecer o que você precisa. Essencialmente, você:
- chamada ManagementFactory.getThreadMXBean () para obter uma instância de ThreadMXBean;
- getAllThreadIds de chamada () no ThreadMXBean resultando enumerar tópicos atuais;
- chamar getThreadInfo () para obter o top n pilha oligoelementos de uma determinada lista de tópicos.