Come rintracciare un programma Java?


25

Come amministratore di sistema a volte incontro situazioni in cui un programma si comporta in modo anomalo, senza creare errori o creare messaggi di errore senza senso.

In passato - prima dell'arrivo di Java - c'erano due contromisure:

  1. Se nient'altro aiuta - RTFM ;-)
  2. Se anche 1. non aiuta - traccia le chiamate di sistema e guarda cosa sta succedendo

Di solito lo uso strace -fper questo compito con Linux (altri sistemi operativi hanno strumenti di traccia simili). Ora, mentre questo di solito funziona bene per qualsiasi programma vecchio stile, la traccia diventa molto sfocata quando si fa lo stesso su un processo java . Ci sono così tante chiamate di sistema apparentemente estranee a qualsiasi azione reale, che è terribile cercare in una simile discarica.

Ci sono modi migliori per farlo (se il codice sorgente non è disponibile)?

Risposte:


16

Come ckhan ha menzionato, jstackè fantastico perché fornisce la traccia dello stack completo di tutti i thread attivi nella JVM. Lo stesso può essere ottenuto su stderr della JVM usando SIGQUIT.

Un altro strumento utile è jmapche può prendere un dump dell'heap dal processo JVM usando il PID del processo:

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

Questo dump dell'heap può essere caricato in strumenti come visualvm(che ora fa parte dell'installazione Oracle java sdk standard, denominata jvisualvm). Inoltre, VisualVM può connettersi alla JVM in esecuzione e visualizzare informazioni sulla JVM, inclusi i grafici dell'utilizzo interno della CPU, il numero di thread e l'utilizzo dell'heap, ottimo per rintracciare le perdite.

Un altro strumento, jstatpuò raccogliere statistiche di garbage collection per la JVM per un periodo di tempo molto simile a vmstat quando eseguito con un argomento numerico (ad es vmstat 3.).

Infine, è possibile utilizzare un agente Java per inviare la strumentazione su tutti i metodi di tutti gli oggetti in fase di caricamento. La biblioteca javassistpuò aiutare a renderlo molto facile da fare. Quindi, è possibile aggiungere la propria traccia. La parte difficile con ciò sarebbe trovare un modo per ottenere l'output di traccia solo quando lo volevi e non sempre, il che probabilmente rallenterebbe la JVM a una scansione. C'è un programma chiamato dtraceche funziona in questo modo. L'ho provato, ma non ha avuto molto successo. Si noti che gli agenti non possono strumentare tutte le classi perché quelle necessarie per avviare la JVM vengono caricate prima che l'agente possa strumentare, quindi è troppo tardi per aggiungere la strumentazione a quelle classi.

Il mio suggerimento : inizia con VisualVM e vedi se ti dice cosa devi sapere poiché può mostrare i thread correnti e le statistiche importanti per la JVM.


A proposito, questa è una domanda fantastica; Spero che più persone aggiungano risposte con altre idee. Quando ho chiesto alle persone che lavorano con Java per molti anni di tracciare, mi hanno dato sguardi vuoti. Forse semplicemente non conoscono la bellezza della straccia.
ash

10

Allo stesso modo, quando si esegue il debug di programmi che sono andati male su un sistema Linux, è possibile utilizzare strumenti simili per eseguire il debug di JVM in esecuzione sul sistema.

Strumento n. 1 - jvmtop

Analogamente top, puoi usare jvmtop per vedere quali sono le classi all'interno delle JVM in esecuzione sul tuo sistema. Una volta installato lo invochi in questo modo:

$ jvmtop.sh

Il suo output ha uno stile simile a quello dello strumento 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

Strumento n. 2 - jvmmonitor

Un'altra alternativa è utilizzare jvmmonitor . JVM Monitor è un profiler Java integrato con Eclipse per monitorare CPU, thread e utilizzo della memoria delle applicazioni Java. Puoi usarlo per trovare automaticamente le JVM in esecuzione sull'host locale oppure puoi connetterti alle JVM remote usando port @ host.

ss di jvmmonitor

Strumento n. 3 - visualvm

visualvm è probabilmente lo "strumento" da raggiungere per il debug di problemi con JVM. Il suo set di funzionalità è piuttosto profondo e puoi dare un'occhiata molto in profondità alle viscere.

Profilo delle prestazioni dell'applicazione o analisi dell'allocazione di memoria:

ss di visualvm # 2

Prendi e visualizza i dump del thread:

ss di visualvm # 3

Riferimenti


4

Prendere in considerazione jstack. Non proprio una partita per strace, più un pstackanalogo, ma almeno ti darà una foto di un'istantanea in tempo. Potresti metterli insieme per ottenere una traccia grezza se dovessi.

Vedi anche i suggerimenti in questo articolo SO: /programming/1025681/call-trace-in-java


2

Se stai usando RHEL OpenJDK (o simile, il punto è che non è il JDK di Oracle), puoi usare SystemTap per questo.

Alcune sonde sono attivate utilizzando le opzioni della riga di comando java -XX:+DTraceMethodProbes, -XX:+DTraceAllocProbes, -XX:+DTraceMonitorProbes. Si noti che l'abilitazione di queste sonde influirà significativamente sulle prestazioni del programma.

Ecco un esempio di SystemTap Script:

#!/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);
}

È inoltre possibile utilizzare jstack()per ottenere lo stack Java del processo, ma funzionerà solo se si avvia SystemTap prima di JVM.


Si noti che SystemTap traccia ogni metodo. Inoltre, non è in grado di ottenere gli argomenti del metodo. Un'altra opzione è quella di utilizzare le funzionalità di traccia JVM che si chiama JVMTI. Una delle implementazioni JVMTI più famose è BTrace .


0

Si consiglia di provare Jackplay , che è uno strumento di tracciamento JVM che consente di tracciare l'immissione del metodo ed uscire senza modificare il codice o ridistribuire.


Non è possibile collegarlo a una JVM in esecuzione. A parte questo - strumento interessante
Nils
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.