Como rastrear um programa java?

25

Como administrador de sistema, às vezes enfrento situações em que um programa se comporta de maneira anormal, sem criar erros ou criar mensagens de erro sem sentido.

No passado - antes da entrada do Java - havia duas contramedidas:

  1. Se nada mais ajudar - RTFM ;-)
  2. Se o 1. nem ajuda - rastreie as chamadas do sistema e veja o que está acontecendo

Eu normalmente uso strace -fpara esta tarefa com o Linux (outro sistema operacional possui ferramentas de rastreamento semelhantes). Agora, embora isso geralmente funcione bem para qualquer programa antiquado, o rastreamento fica muito confuso ao fazer o mesmo em um java . Existem tantas chamadas de sistema aparentemente sem relação com qualquer ação real, que é terrível procurar por esse despejo.

Existem maneiras melhores de fazer isso (se o código-fonte não estiver disponível)?

Nils
fonte

Respostas:

16

Como ckhan mencionou, jstacké ótimo porque fornece o rastreamento completo da pilha de todos os encadeamentos ativos na JVM. O mesmo pode ser obtido no stderr da JVM usando SIGQUIT.

Outra ferramenta útil é a jmapque pode obter um dump de heap do processo da JVM usando o PID do processo:

jmap -dump:file=/tmp/heap.hprof $PID

Esse dump de heap pode ser carregado em ferramentas como visualvm(que agora faz parte da instalação padrão do Oracle java sdk, denominada jvisualvm). Além disso, o VisualVM pode se conectar à JVM em execução e exibir informações sobre a JVM, incluindo gráficos do uso interno da CPU, contagens de encadeamentos e uso de heap - ótimo para rastrear vazamentos.

Outra ferramenta, jstatpode coletar estatísticas de coleta de lixo para a JVM durante um período semelhante à vmstat quando executada com um argumento numérico (por exemplo,vmstat 3 ).

Por fim, é possível usar um Java Agent para enviar a instrumentação a todos os métodos de todos os objetos no momento do carregamento. A biblioteca javassistpode ajudar a tornar isso muito fácil de fazer. Portanto, é possível adicionar seu próprio rastreio. A parte mais difícil disso seria encontrar uma maneira de obter saída de rastreio apenas quando você quisesse e não o tempo todo, o que provavelmente atrasaria a JVM para um rastreamento. Existe um programa chamado dtraceque funciona dessa maneira. Eu tentei, mas não foi muito bem sucedido. Observe que os agentes não podem instrumentar todas as classes porque os necessários para inicializar a JVM são carregados antes que o agente possa instrumentar, e é tarde demais para adicionar instrumentação a essas classes.

Minha sugestão - comece com o VisualVM e veja se isso lhe diz o que você precisa saber, pois ele pode mostrar os threads atuais e estatísticas importantes para a JVM.

cinza
fonte
A propósito, esta é uma pergunta impressionante; Espero que mais pessoas adicionem respostas com outras idéias. Quando perguntei às pessoas que trabalham com Java por muitos anos sobre rastreamento, elas me deram olhares em branco. Talvez eles simplesmente não conheçam a grandiosidade do traço.
ash
10

Da mesma forma, ao depurar programas que deram errado em um sistema Linux, você pode usar ferramentas semelhantes para depurar JVMs em execução no sistema.

Ferramenta # 1 - jvmtop

Semelhante top, você pode usar o jvmtop para ver quais classes estão fazendo dentro das JVMs em execução no seu sistema. Uma vez instalado, você o invoca assim:

$ jvmtop.sh

Sua saída possui um estilo semelhante para parecer com a ferramenta top:

 JvmTop 0.8.0 alpha   amd64  8 cpus, Linux 2.6.32-27, load avg 0.12
 http://code.google.com/p/jvmtop

  PID MAIN-CLASS      HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 3370 rapperSimpleApp  165m  455m  109m  176m  0.12%  0.00% S6U37 web        21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager   11m   28m   23m  130m  0.00%  0.00% S6U37 web        31
19187 m.jvmtop.JvmTop   20m 3544m   13m  130m  0.93%  0.47% S6U37 web        20
16733 artup.Bootstrap  159m  455m  166m  304m  0.12%  0.00% S6U37 web        46

Ferramenta # 2 - jvmmonitor

Outra alternativa é usar o jvmmonitor . O JVM Monitor é um profiler Java integrado ao Eclipse para monitorar CPU, threads e uso de memória de aplicativos Java. Você pode usá-lo para encontrar automaticamente JVMs em execução no host local ou pode se conectar a JVMs remotas usando uma porta @ host.

ss do jvmmonitor

Ferramenta # 3 - visualvm

visualvm provavelmente é "a ferramenta" a ser alcançada ao depurar problemas com a JVM. Seu conjunto de recursos é bastante profundo e você pode obter uma visão mais profunda das entranhas.

Perfile o desempenho do aplicativo ou analise a alocação de memória:

ss do visualvm # 2

Obter e exibir despejos de linha:

ss do visualvm # 3

Referências

slm
fonte
4

Considere jstack. Não é exatamente uma partida para strace, mais de umpstack -análogo, mas pelo menos lhe dará uma imagem de um instantâneo a tempo. Poderia amarrá-los para obter um rastro bruto, se necessário.

Consulte também as sugestões deste artigo do SO: /programming/1025681/call-trace-in-java

ckhan
fonte
2

Se você estiver usando o RHEL OpenJDK (ou semelhante, o ponto é que não é o JDK do Oracle), você pode usar o SystemTap para isso.

Algumas sondas estão ativadas usando as opções de linha de comando java -XX:+DTraceMethodProbes, -XX:+DTraceAllocProbes, -XX:+DTraceMonitorProbes. Observe que a ativação dessas análises afetará significativamente o desempenho do programa.

Aqui está um exemplo de script SystemTap:

#!/usr/bin/stap

probe hotspot.class_loaded {
    printf("%12s [???] %s\n", name, class);
}

probe hotspot.method_entry, 
      hotspot.method_return {
    printf("%12s [%3d] %s.%s\n", name, thread_id, class, method);
}

probe hotspot.thread_start, 
      hotspot.thread_stop {
    printf("%12s [%3d] %s\n", name, id, thread_name);
}

probe hotspot.monitor_contended_enter, 
      hotspot.monitor_contended_exit {
    printf("%12s [%3d] %s\n", name, thread_id, class);
}

Você também pode usar jstack()para obter a pilha Java do processo, mas só funcionará se você iniciar o SystemTap antes da JVM.


Observe que o SystemTap rastreará todos os métodos. Também não é possível obter argumentos do método. Outra opção é usar os próprios recursos de rastreio da JVM, que são chamados de JVMTI. Uma das implementações mais famosas da JVMTI é o BTrace .

myaut
fonte
0

É recomendável experimentar o Jackplay , que é uma ferramenta de rastreamento da JVM, permitindo rastrear a entrada e a saída do método sem alteração ou reimplantação do código.

alfredx
fonte
Você não pode anexá-lo a uma JVM em execução. Além disso - ferramenta interessante
Nils