Come ottenere un thread e un heap dump di un processo Java su Windows che non è in esecuzione in una console


Ho un'applicazione Java che eseguo da una console che a sua volta esegue un altro processo Java. Voglio ottenere un dump thread/heap di quel processo figlio.

Su Unix, potrei fare un kill -3 <pid> ma su Windows AFAIK l'unico modo per ottenere un dump del thread è Ctrl-Break nella console. Ma questo mi dà solo la discarica del processo genitore, non del bambino.

C'è un altro modo per ottenere quel dump dell'heap?

Author: Kasun Siyambalapitiya, 2009-01-02

20 answers

Puoi usare jmap per ottenere un dump di qualsiasi processo in esecuzione, supponendo che tu conosca pid.

Utilizzare Task Manager o Resource Monitor per ottenere il pid. Quindi

jmap -dump:format=b,file=cheap.hprof <pid>

Per ottenere l'heap per quel processo.

 390
Author: rkaganda, 2019-06-26 01:03:29

Stai confondendo due diversi dump java. kill -3 genera un dump di thread, non un dump di heap.

Thread dump = stack tracce per ogni thread nell'output JVM a stdout come testo.

Heap dump = contenuto della memoria per l'output del processo JVM in un file binario.

Per eseguire un dump del thread su Windows, CTRL+BREAK se la tua JVM è il processo in primo piano è il modo più semplice. Se hai una shell simile a Unix su Windows come Cygwin o MobaXterm, puoi usare kill -3 {pid} come puoi fare in Unix.

Per eseguire un dump del thread in Unix, CTRL+C se la tua JVM è il processo in primo piano o kill -3 {pid} funzionerà finché ottieni il PID giusto per la JVM.

Con entrambe le piattaforme, Java viene fornito con diverse utility che possono aiutare. Per le discariche di thread, jstack {pid} è la soluzione migliore. http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.html

Solo per finire la domanda di dump: i dump heap non sono comunemente utilizzati perché sono difficili da interpretare. Ma hanno molte informazioni utili in loro se sai dove / come guardarli. L'uso più comune è quello di individuare le perdite di memoria. È buona norma impostare -D sulla riga di comando java in modo che il dump dell'heap venga generato automaticamente su un OutOfMemoryError, -XX:+HeapDumpOnOutOfMemoryError, ma è anche possibile attivare manualmente un dump dell'heap. Il modo più comune è quello di utilizzare l'utilità java jmap.

NOTA: questa utility non è disponibile su tutte le piattaforme. A partire da JDK 1.6, jmap è disponibile su Windows.

Una riga di comando di esempio sarebbe simile a

jmap -dump:file=myheap.bin {pid of the JVM}

L'uscita " myheap.bin " non è leggibile dall'uomo (per la maggior parte di noi), e avrete bisogno di uno strumento per analizzarlo. La mia preferenza è MAT. http://www.eclipse.org/mat /

 118
Author: Derek, 2020-06-20 09:12:55

Penso che il modo migliore per creare .il file hprof nel processo Linux è con il comando jmap . Ad esempio: jmap -dump:format=b,file=filename.hprof {PID}

 32
Author: Roberto Flores, 2013-10-14 22:49:10

Oltre a utilizzare il jconsole/visualvm menzionato, è possibile utilizzare jstack -l <vm-id> su un'altra finestra della riga di comando e acquisire tale output.

Il può essere trovato usando il task manager (è l'id del processo su Windows e unix) o usando jps.

Sia jstack che jps sono inclusi nella versione 6 di Sun JDK e successive.

 19
Author: ankon, 2015-07-01 09:07:33

Consiglio il Java VisualVM distribuito con il JDK (jvisualvm.exe). Può connettersi dinamicamente e accedere ai thread e all'heap. Ho trovato in inestimabile per alcuni problemi.

 17
Author: Lawrence Dol, 2009-01-02 19:25:54

Se sei su server-jre 8 e versioni successive puoi usare questo:

jcmd PID GC.heap_dump /tmp/dump
 17
Author: Atul Soman, 2017-10-03 15:00:04

Prova una delle seguenti opzioni.

  1. Per JVM a 32 bit:

    jmap -dump:format=b,file=<heap_dump_filename> <pid>
    
  2. Per JVM a 64 bit (citando esplicitamente):

    jmap -J-d64 -dump:format=b,file=<heap_dump_filename> <pid>
    
  3. Per JVM a 64 bit con algoritmo G1GC nei parametri VM (solo l'heap di oggetti live viene generato con algoritmo G1GC):

    jmap -J-d64 -dump:live,format=b,file=<heap_dump_filename> <pid>
    

Domanda SE correlata: Errore di dump dell'heap Java con il comando jmap: EOF prematuro

Dai un'occhiata a varie opzioni di {[3] } a questo articolo

 15
Author: Ravindra babu, 2017-10-03 15:01:38

Se si desidera un heapdump su out-of-memory, è possibile avviare Java con l'opzione -XX:-HeapDumpOnOutOfMemoryError

C. f. Pagina di riferimento Opzioni JVM

 13
Author: Daniel Winterstein, 2012-01-18 15:59:12

È possibile eseguire jconsole (incluso con l'SDK di Java 6) quindi connettersi all'applicazione Java. Ti mostrerà ogni thread in esecuzione e la sua traccia di stack.

 7
Author: Steve Kuo, 2009-01-02 18:51:05

È possibile inviare il kill -3 <pid> da Cygwin. È necessario utilizzare le opzioni Cygwin ps per trovare i processi di Windows, quindi inviare il segnale a tale processo.

 7
Author: krosenvold, 2017-10-03 14:58:31

Devi reindirizzare l'output dal secondo eseguibile java a qualche file. Quindi, usa SendSignal per inviare "-3" al tuo secondo processo.

 5
Author: Yoni Roit, 2019-01-10 08:10:28

Se si utilizza JDK 1.6 o superiore, è possibile utilizzare il comando jmap per eseguire un dump heap di un processo Java, la condizione è che si debba conoscere ProcessID.

Se si è sulla macchina Windows, è possibile utilizzare Task Manager per ottenere PID. Per la macchina Linux è possibile utilizzare varietà di comandi come ps -A | grep java o netstat -tupln | grep java o top | grep java, dipende dall'applicazione.

Quindi puoi usare il comando come jmap -dump:format=b,file=sample_heap_dump.hprof 1234 dove 1234 è PID.

Ci sono varietà di strumento disponibile per interpretare il file hprof. Consiglierò lo strumento visualvm di Oracle, che è semplice da usare.

 3
Author: Badal, 2016-02-05 03:56:01

Se non è possibile (o non si desidera) utilizzare la console/terminale per qualche motivo, esiste una soluzione alternativa. Puoi fare in modo che l'applicazione Java stampi il dump del thread per te. Il codice che raccoglie la traccia Stack è ragionevole semplice e può essere collegato a un pulsante o un'interfaccia web.

private static String getThreadDump() {
    Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();

    StringBuilder out = new StringBuilder();
    for (Map.Entry<Thread, StackTraceElement[]> entry : allStackTraces.entrySet()) {
        Thread thread = entry.getKey();
        StackTraceElement[] elements = entry.getValue();
        out.append(String.format("%s | prio=%d | %s", thread.getName(), thread.getPriority(), thread.getState()));
        out.append('\n');

        for (StackTraceElement element : elements) {
            out.append(element.toString()).append('\n');
        }
        out.append('\n');
    }
    return out.toString();
}

Questo metodo restituirà una stringa simile a questa:

main | prio=5 | RUNNABLE
java.lang.Thread.dumpThreads(Native Method)
java.lang.Thread.getAllStackTraces(Thread.java:1607)
Main.getThreadDump(Main.java:8)
Main.main(Main.java:36)

Monitor Ctrl-Break | prio=5 | RUNNABLE
java.net.PlainSocketImpl.initProto(Native Method)
java.net.PlainSocketImpl.<clinit>(PlainSocketImpl.java:45)
java.net.Socket.setImpl(Socket.java:503)
java.net.Socket.<init>(Socket.java:424)
java.net.Socket.<init>(Socket.java:211)
com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:59)

Finalizer | prio=8 | WAITING
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

Reference Handler | prio=10 | WAITING
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:502)
java.lang.ref.Reference.tryHandlePending(Reference.java:191)
java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

Per chi fosse interessato a una versione Java 8 con stream, il codice è ancora più compatto:

private static String getThreadDump() {
    Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
    StringBuilder out = new StringBuilder();
    allStackTraces.forEach((thread, elements) -> {
        out.append(String.format("%s | prio=%d | %s", thread.getName(), thread.getPriority(), thread.getState()));
        out.append('\n');

        Arrays.stream(elements).forEach(element -> out.append(element.toString()).append('\n'));
        out.append('\n');
    });
    return out.toString();
}

È possibile prova facilmente questo codice con:

System.out.print(getThreadDump());
 3
Author: HugoTeixeira, 2018-08-03 02:00:25

Il seguente script utilizza PsExec per connettersi a un'altra sessione di Windows in modo che funzioni anche quando è connesso tramite il servizio Desktop remoto.

Ho scritto un piccolo script batch per Java 8 (usando PsExec e jcmd) denominato jvmdump.bat, che scarica i thread, l'heap, le proprietà del sistema e gli argomenti JVM.

:: set the paths for your environment
set PsExec=C:\Apps\SysInternals\PsExec.exe
set JAVA_HOME=C:\Apps\Java\jdk1.8.0_121
set DUMP_DIR=C:\temp

@echo off

set PID=%1

if "%PID%"=="" (
    echo usage: jvmdump.bat {pid}
    exit /b
)

for /f "tokens=2,3,4 delims=/ " %%f in ('date /t') do set timestamp_d=%%h%%g%%f
for /f "tokens=1,2 delims=: " %%f in ('time /t') do set timestamp_t=%%f%%g
set timestamp=%timestamp_d%%timestamp_t%
echo datetime is: %timestamp%

echo ### Version >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.version >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Uptime >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.uptime >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Command >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.command_line >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Flags >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.flags >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Properties >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.system_properties >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% Thread.print -l >"%DUMP_DIR%\%PID%-%timestamp%-threads.log"

%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% GC.heap_dump "%DUMP_DIR%\%PID%-%timestamp%-heap.hprof"

echo Dumped to %DUMP_DIR%

Deve essere eseguito nella stessa sessione Windows dell'utente che ha avviato la JVM, quindi se ci si connette tramite Desktop remoto potrebbe essere necessario avviare un prompt dei comandi in Session 0 ed eseguirlo da lì. ad esempio

%PsExec% -s -h -d -i 0 cmd.exe

Questo ti chiederà (fai clic sull'icona della barra delle applicazioni in basso) di View the message nella sessione interattiva, che ti porterà alla nuova console nell'altra sessione da cui puoi eseguire lo script jvmdump.bat.

 3
Author: isapir, 2020-05-14 16:24:53

Come ottenere l'ID del processo dell'applicazione java?

Eseguire il comando 'jcmd' per ottenere l'ID di processo delle applicazioni java.

Come ottenere il dump del filo?

Filo PID Jcmd.stampa > filo.dump

Riferimento collegamento

Puoi anche usare jstack per ottenere il dump del thread (jstack PID > thread.discarica). Riferimento collegamento

Come ottenere heap dump?

Usa lo strumento jmap per ottenere il dump dell'heap. jmap-F - dump: live, format = b, file = heap.bin PID

PID sta per id processo dell'applicazione. Riferimento collegamento

 2
Author: Hari Krishna, 2020-01-03 07:59:44

Forse jcmd ?

L'utilità Jcmd viene utilizzata per inviare richieste di comandi diagnostici alla JVM, dove queste richieste sono utili per controllare le registrazioni di volo Java, risolvere i problemi e diagnosticare le applicazioni JVM e Java.

Lo strumento jcmd è stato introdotto con Java 7 di Oracle ed è particolarmente utile nella risoluzione dei problemi con le applicazioni JVM utilizzandolo per identificare gli ID dei processi Java (simili a jps), acquisire heap dump (simili a jmap), acquisire thread dump (simile a jstack), visualizzazione delle caratteristiche della macchina virtuale come le proprietà del sistema e i flag della riga di comando (simile a jinfo) e acquisizione di statistiche di garbage collection (simile a jstat). Lo strumento jcmd è stato chiamato "un coltellino svizzero per indagare e risolvere i problemi con l'applicazione JVM" e una "gemma nascosta."

Ecco il processo che dovrai utilizzare per richiamare jcmd:

  1. Vai a jcmd <pid> GC.heap_dump <file-path>
  2. In cui
  3. pid: è un ID processo Java, per che verrà catturato anche il dump dell'heap, il
  4. file-path: è un percorso di file in cui viene stampato il dump dell'heap.

Check it out per ulteriori informazioni su come prendere Java heap dump .

 1
Author: Johnny, 2019-05-29 13:49:53

Seguito di Visualvm:

Se è "impossibile connettersi" alla JVM jvisualvm, perché non iniziare con la JVM arguments (e remoto), eseguire jstatd sulla macchina remota, quindi, supponendo che si dispone di una connessione diretta, aggiungere un "host remoto" in visualvm, fare doppio clic sul nome host, e tutte le altre JVM in quella scatola magicamente " la mostra di visualvm.

Se non si dispone di "connessione diretta" alle porte su quella casella, è possibile farlo anche tramite un delega .

Una volta che puoi vedere il processo che desideri, esegui il drill in jvisualvm e usa la scheda monitor - > pulsante "heapdump".

 0
Author: rogerdpack, 2019-01-28 18:43:25

Sotto il codice java viene utilizzato per ottenere il dump dell'heap di un processo Java fornendo PID. Il programma utilizza la connessione JMX remota per scaricare l'heap. Può essere utile per qualcuno.

import java.lang.management.ManagementFactory;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.reflect.Method;

public class HeapDumper {

public static final String HOST = "192.168.11.177";
public static final String PORT = "1600";
public static final String FILE_NAME = "heapDump.hprof";
public static final String FOLDER_PATH = "C:/";
private static final String HOTSPOT_BEAN_NAME ="com.sun.management:type=HotSpotDiagnostic";

public static void main(String[] args) {
    if(args.length == 0) {
        System.out.println("Enter PID of the Java Process !!!");
        return;
    }

    String pidString = args[0];
    int pid = -1;
    if(pidString!=null && pidString.length() > 0) {
        try {
            pid = Integer.parseInt(pidString);
        }
        catch(Exception e) {
            System.out.println("PID is not Valid !!!");
            return;
        }
    }
    boolean isHeapDumpSuccess = false;
    boolean live = true;
    if(pid > 0) {
        MBeanServerConnection beanServerConn = getJMXConnection();

        if(beanServerConn!=null) {
            Class clazz = null;
            String dumpFile = FOLDER_PATH+"/"+FILE_NAME;
            try{
                clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
                Object hotspotMBean = ManagementFactory.newPlatformMXBeanProxy(beanServerConn, HOTSPOT_BEAN_NAME, clazz);
                Method method = clazz.getMethod("dumpHeap", new Class[]{String.class , boolean.class});
                method.setAccessible(true);
                method.invoke(hotspotMBean , new Object[] {dumpFile, new Boolean(live)});
                isHeapDumpSuccess = true;
            }
            catch(Exception e){
                e.printStackTrace();
                isHeapDumpSuccess = false;
            }
            finally{
                clazz = null;
            }
        }
    }

    if(isHeapDumpSuccess){
        System.out.println("HeapDump is Success !!!");
    }
    else{
        System.out.println("HeapDump is not Success !!!");
    }
}

private static MBeanServerConnection getJMXConnection() {
    MBeanServerConnection mbeanServerConnection = null;
    String urlString = "service:jmx:rmi:///jndi/rmi://" + HOST + ":" + PORT + "/jmxrmi";
    try {
        JMXServiceURL url = new JMXServiceURL(urlString);
        JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
        mbeanServerConnection = jmxConnector.getMBeanServerConnection();
        System.out.println("JMX Connection is Success for the URL :"+urlString);
    }
    catch(Exception e) {
        System.out.println("JMX Connection Failed !!!");
    }
    return mbeanServerConnection;
}

}

 0
Author: Ramesh Subramanian, 2019-05-16 07:41:08

Inorder to take thread dump/heap dump from a child java process in Windows, è necessario identificare l'ID del processo figlio come primo passo.

Emettendo il comando: jps sarà possibile ottenere tutti gli ID di processo java in esecuzione sul computer Windows. Da questo elenco è necessario selezionare Id processo figlio. Una volta che hai l'ID del processo figlio, ci sono varie opzioni per catturare il dump del thread e i dump dell'heap.

Acquisizione di discariche di thread:

Ci sono 8 opzioni per discariche di thread di acquisizione:

  1. jstack
  2. uccidere -3
  3. jvisualVM
  4. JMC
  5. Finestre (Ctrl + Pausa)
  6. ThreadMXBean
  7. Strumenti APM
  8. jcmd

I dettagli su ciascuna opzione possono essere trovati in questo articolo . Una volta acquisiti i dump dei thread di acquisizione, puoi utilizzare strumenti come fastThread, Samuraito analizza i dump dei thread.

Acquisizione di Heap Dump:

Ci sono 7 opzioni per cattura i dump dell'heap:

  1. Jmap

  2. - XX: + HeapDumpOnOutOfMemoryError

  3. Jcmd

  4. JVisualVM

  5. JMX

  6. Approccio programmatico

  7. Console di amministrazione

I dettagli su ciascuna opzione possono essere trovati in questo articolo . Una volta catturato il dump dell'heap, è possibile utilizzare strumenti come Strumento di analisi della memoria Eclipse, HeapHero per analizzare i dump heap catturati.

 0
Author: Jim T, 2020-06-20 09:12:55

Su un Oracle JDK, abbiamo un comando chiamato jmap (disponibile nella cartella bin di Java Home). l'utilizzo del comando avviene come segue

Jmap (opzione) (pid)

Esempio: jmap-dump:live,format=b,file=heap.bin (pid)

 -1
Author: Suresh Ram, 2018-02-22 12:38:07