Comment obtenir un vidage de thread et de tas d'un processus Java sur Windows qui ne s'exécute pas dans une console


J'ai une application Java que j'exécute à partir d'une console qui exécute à son tour un autre processus Java. Je veux obtenir un vidage de thread/tas de ce processus enfant.

Sur Unix, je pourrais faire un kill -3 <pid> mais sous Windows AFAIK, le seul moyen d'obtenir un vidage de thread est Ctrl-Break dans la console. Mais cela ne me donne que le vidage du processus parent, pas l'enfant.

Existe-t-il un autre moyen d'obtenir ce vidage de tas?

Author: Kasun Siyambalapitiya, 2009-01-02

20 answers

Vous pouvez utiliser jmap pour obtenir un vidage de tout processus en cours d'exécution, en supposant que vous connaissez le pid.

Utilisez le Gestionnaire de tâches ou le moniteur de ressources pour obtenir le pid. Puis

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

Pour obtenir le tas pour ce processus.

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

Vous confondez deux décharges java différentes. kill -3 génère un vidage de threads, pas un vidage de tas.

Thread dump = stack trace pour chaque thread de la sortie JVM vers stdout sous forme de texte.

Heap dump = contenu de la mémoire pour la sortie du processus JVM dans un fichier binaire.

Pour prendre un vidage de thread sous Windows, CTRL+BREAK si votre JVM est le processus de premier plan est le moyen le plus simple. Si vous avez un shell de type Unix sur Windows comme Cygwin ou MobaXterm, vous pouvez utiliser kill -3 {pid} comme vous pouvez le faire sous Unix.

Pour faire un vidage de threads sous Unix, CTRL+C si votre JVM est le processus de premier plan ou kill -3 {pid} fonctionnera tant que vous obtenez le bon PID pour la JVM.

Avec l'une ou l'autre plate-forme, Java est livré avec plusieurs utilitaires qui peuvent aider. Pour les vidages de threads, jstack {pid} est votre meilleur pari. http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.html

Juste pour terminer la question de vidage: les vidages de tas ne sont pas courants utilisé parce qu'ils sont difficiles à interpréter. Mais, ils ont beaucoup d'informations utiles, si vous savez où et comment regarder. L'utilisation la plus courante consiste à localiser les fuites de mémoire. C'est une bonne pratique de définir le -D sur la ligne de commande java afin que le vidage de tas soit généré automatiquement lors d'une OutOfMemoryError, -XX:+HeapDumpOnOutOfMemoryError Mais, vous pouvez également déclencher manuellement un vidage de tas. La plus courante est d'utiliser l'utilitaire java jmap.

REMARQUE: cet utilitaire n'est pas disponible sur toutes les plateformes. Depuis JDK 1.6, jmap est disponible sur Windows.

Un exemple de ligne de commande ressemblerait à quelque chose comme

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

La sortie "myheap.bin" n'est pas lisible par l'homme (pour la plupart d'entre nous), et vous aurez besoin d'un outil pour l'analyser. Ma préférence est MAT. http://www.eclipse.org/mat/

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

Je pense que la meilleure façon de créer .le fichier hprof dans le processus Linux est avec la commande jmap . Par exemple: jmap -dump:format=b,file=filename.hprof {PID}

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

En plus d'utiliser le jconsole/visualvm mentionné, vous pouvez utiliser jstack -l <vm-id> sur une autre fenêtre de ligne de commande et capturer cette sortie.

Le peut être trouvé en utilisant le gestionnaire des tâches (c'est l'id de processus sous Windows et unix), ou en utilisant jps.

Les deux jstack et jps sont inclus dans la version 6 et supérieure de Sun JDK.

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

Je recommande le Java VisualVM distribué avec le JDK (jvisualvm.EXE). Il peut se connecter dynamiquement et accéder aux threads et au tas. J'ai trouvé dans inestimable pour certains problèmes.

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

Si vous êtes sur server-jre 8 et au-dessus, vous pouvez utiliser ceci:

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

Essayez l'une des options ci-dessous.

  1. Pour la JVM 32 bits:

    jmap -dump:format=b,file=<heap_dump_filename> <pid>
    
  2. Pour la JVM 64 bits (citant explicitement):

    jmap -J-d64 -dump:format=b,file=<heap_dump_filename> <pid>
    
  3. Pour la JVM 64 bits avec l'algorithme G1GC dans les paramètres de la machine virtuelle (Seul le tas d'objets vivants est généré avec l'algorithme G1GC):

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

Question SE connexe: Erreur de vidage de tas Java avec la commande jmap: EOF prématuré

Jetez un oeil à diverses options de jmap à cet article

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

Si vous voulez un heapdump de mémoire, vous pouvez commencer à Java avec l'option -XX:-HeapDumpOnOutOfMemoryError

C. f. Page de référence des options JVM

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

Vous pouvez exécuter jconsole (inclus avec le SDK de Java 6) puis vous connecter à votre application Java. Il vous montrera chaque Thread en cours d'exécution et sa trace de pile.

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

Vous pouvez envoyer le kill -3 <pid> depuis Cygwin. Vous devez utiliser les options Cygwin ps pour trouver les processus Windows, puis envoyez simplement le signal à ce processus.

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

Vous devez rediriger la sortie du deuxième exécutable java vers un fichier. Ensuite, utilisez SendSignal à envoyer "-3" à votre deuxième processus.

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

Si vous utilisez JDK 1.6 ou supérieur, Vous pouvez utiliser la commande jmap pour prendre un vidage de tas d'un processus Java, la condition est que vous devriez connaître ProcessID.

Si vous êtes sur la machine Windows, vous pouvez utiliser le Gestionnaire des tâches pour obtenir PID. Pour la machine Linux, vous pouvez utiliser des variétés de commandes comme ps -A | grep java ou netstat -tupln | grep java ou top | grep java, cela dépend de votre application.

Ensuite, vous pouvez utiliser la commande comme jmap -dump:format=b,file=sample_heap_dump.hprof 1234 où 1234 est PID.

Il existe des variétés de outil disponible pour interpréter le fichier hprof. Je recommanderai l'outil visualvm d'Oracle, qui est simple à utiliser.

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

Si vous ne pouvez pas (ou ne voulez pas) utiliser la console/terminal pour une raison quelconque, il existe une solution alternative. Vous pouvez faire en sorte que l'application Java imprime le vidage de thread pour vous. Le code qui collecte la trace de la pile est raisonnable et simple et peut être attaché à un bouton ou à une interface 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();
}

Cette méthode retournera une chaîne qui ressemble à ceci:

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)

Pour ceux qui s'intéressent à une version Java 8 avec des flux, le code est encore plus compact:

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();
}

Vous pouvez testez facilement ce code avec:

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

Le script suivant utilise PsExec pour se connecter à une autre session Windows, de sorte qu'il fonctionne même lorsqu'il est connecté via le service Remote Desktop.

J'ai écrit un petit script batch pour Java 8 (en utilisant PsExec et jcmd) nommé jvmdump.bat, qui vide les threads, le tas, les propriétés système et les arguments 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%

Il doit être exécuté dans la même session Windows de l'utilisateur qui a démarré la JVM, donc si vous vous connectez via Remote Desktop, vous devrez peut-être lancer une invite de commande dans Session 0 et exécutez-le à partir de là. par exemple

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

Cela vous demandera (cliquez sur l'icône de la barre en bas) de View the message dans la session interactive, qui vous mènera à la nouvelle console dans l'autre session à partir de laquelle vous pouvez exécuter le jvmdump.bat script.

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

Comment faire pour obtenir l'id de processus de l'application java?

Exécutez la commande 'jcmd" pour obtenir l'id de processus des applications java.

Comment obtenir un vidage de thread?

Fil PID Jcmd.imprimer > thread.vidage

Référence lien

Vous pouvez même utiliser jstack pour obtenir un vidage de thread (jstack PID > thread.dump). Référence lien

Comment obtenir une décharge de tas?

Utilisez l'outil jmap pour obtenir un vidage de tas. jmap-F -vidage:live,format=b,fichier=tas.bin PID

PID signifie process id de l'application. Référence lien

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

Peut-être jcmd?

L'utilitaire Jcmd est utilisé pour envoyer des demandes de commande de diagnostic à la JVM, où ces demandes sont utiles pour contrôler les enregistrements de vol Java, dépanner et diagnostiquer les applications JVM et Java.

L'outil jcmd a été introduit avec Java 7 d'Oracle et est particulièrement utile pour résoudre les problèmes avec les applications JVM en l'utilisant pour identifier les ID des processus Java (similaires à jps), acquérir des décharges de tas (similaires à jmap), acquérir des threads vidages (similaires à jstack), affichage des caractéristiques de la machine virtuelle telles que les propriétés système et les indicateurs de ligne de commande (similaires à jinfo) et acquisition de statistiques de récupération de place (similaires à jstat). L'outil jcmd a été appelé "un couteau suisse pour enquêter et résoudre les problèmes avec votre application JVM" et un "joyau caché."

Voici le processus que vous devrez utiliser pour appeler le jcmd:

  1. Aller à jcmd <pid> GC.heap_dump <file-path>
  2. Dans lequel
  3. pid: est un Id de processus Java, pour dont la décharge de tas sera capturée Aussi, le
  4. file-path: est un chemin de fichier dans lequel le vidage de tas est imprimé.

Consultez-le pour plus d'informations sur la prise de Java heap dump .

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

Suivi Visualvm:

Si vous "ne pouvez pas vous connecter" à votre JVM en cours d'exécution à partir de jvisualvm parce que vous ne l'avez pas démarré avec les bons arguments JVM (et c'est sur la boîte distante), exécutez jstatd sur la boîte distante, puis, en supposant que vous avez une connexion directe, ajoutez-le en tant qu ' "hôte distant" dans visualvm, double-cliquez

Si vous n'avez pas de "connexion directe" aux ports de cette boîte, vous pouvez également le faire via un proxy.

Une fois que vous pouvez voir le processus que vous voulez, percez-le dans jvisualvm et utilisez l'onglet moniteur - > bouton "heapdump".

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

Ci-dessous, le code java est utilisé pour obtenir le vidage de tas d'un processus Java en fournissant PID. Le programme utilise une connexion JMX distante pour vider le tas. Il peut être utile pour certains une.

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

Pour effectuer un vidage de thread/vidage de tas à partir d'un processus java enfant dans Windows, vous devez identifier l'id du processus enfant comme première étape.

En émettant la commande: jps vous pourrez obtenir tous les ID de processus java qui s'exécutent sur votre machine Windows. Dans cette liste, vous devez sélectionner l'id de processus enfant. Une fois que vous avez l'id de processus enfant, il existe différentes options pour capturer le vidage des threads et les vidages de tas.

Capture des vidages de threads:

Il y a 8 options pour capture des vidages de threads:

  1. jstack
  2. tuer -3
  3. jvisualVM
  4. JMC
  5. Windows (Ctrl + Pause)
  6. ThreadMXBean
  7. Outils APM
  8. jcmd

Des détails sur chaque option peuvent être trouvés dans cet article. Une fois que vous avez des vidages de threads de capture, vous pouvez utiliser des outils comme fastThread, Samuraito analyse les vidages de threads.

Capture des décharges de tas:

Il y a 7 options pour capture des décharges de tas:

  1. Les

  2. -XX:+HeapDumpOnOutOfMemoryError

  3. Jcmd

  4. JVisualVM

  5. JMX

  6. Approche Programmatique

  7. Consoles administratives

Des détails sur chaque option peuvent être trouvés dans cet article. Une fois que vous avez capturé le vidage de tas, vous pouvez utiliser des outils comme Outil d'analyse de mémoire Eclipse, HeapHero pour analyser les décharges de tas capturées.

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

Sur un JDK Oracle, nous avons une commande appelée jmap (disponible dans le dossier bin de Java Home). l'utilisation de la commande est la suivante

Jmap (option) (pid)

Exemple: jmap -dump:live,format=b,fichier=tas.bin (pid)

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