Existe-t-il un moyen de vider une trace de pile sans lancer d'exception en java?

Je pense à créer un outil de débogage pour mon application Java.

Je me demande s'il est possible d'obtenir une trace de pile, tout comme Exception.printStackTrace() mais sans lancer d'exception?

Mon but est, dans une méthode donnée, de vider une pile pour voir qui est l'appelant de la méthode.

125
demandé sur bruno 2009-06-03 18:11:58

9 réponses

Vous pouvez également essayer Thread.getAllStackTraces() pour obtenir une carte des traces de pile pour tous les threads qui sont vivants.​​​​​​

70
répondu Ram 2015-04-09 09:14:23

Oui, utilisez simplement

Thread.dumpStack()
190
répondu Rob Di Marco 2009-06-03 14:17:19

Si vous voulez la trace pour seulement le thread actuel (plutôt que tous les threads du système, comme le fait la suggestion de Ram), faites:

Fil.currentThread ().getStackTrace()

Pour trouver l'appelant, faites:

private String getCallingMethodName() {
    StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
    return callingFrame.getMethodName();
}

Et appelez cette méthode depuis la méthode qui a besoin de savoir qui est son appelant. Cependant, un mot d'avertissement: l'index du cadre appelant dans la liste peut varier en fonction de la JVM! Tout dépend du nombre de couches d'appels il y a à l'intérieur getStackTrace avant d'atteindre le point où la trace est générée. Une solution plus robuste serait d'obtenir la trace, et d'itérer dessus à la recherche du Cadre pour getCallingMethodName, puis de faire deux étapes plus loin pour trouver le vrai appelant.

34
répondu Tom Anderson 2009-06-04 10:23:38

Vous pouvez obtenir une trace de pile comme ceci:

Throwable t = new Throwable();
t.printStackTrace();

Si vous voulez accéder au cadre, vous pouvez utiliser T. getStackTrace() pour obtenir un tableau de cadres de pile.

Sachez que cette stacktrace (comme toute autre) peut manquer des cadres si le compilateur de hotspot a été occupé à optimiser les choses.

27
répondu Gerco Dries 2009-06-03 14:16:12

Notez ce fil.dumpStack() lance une exception:

new Exception("Stack trace").printStackTrace();
11
répondu Ariel T 2013-01-31 15:06:20

Vous pouvez également envoyer un signal à la JVM pour exécuter le Thread.getAllStackTraces() sur un processus Java en cours d'exécution en envoyant un signal QUIT au processus.

Sur Unix/Linux utilisez:

kill -QUIT process_id, où process_id est le numéro de processus de votre programme Java.

Sous Windows, vous pouvez appuyer sur Ctrl-Break dans l'application, bien que vous ne le voyiez généralement pas sauf si vous exécutez un processus de console.

JDK6 a introduit une autre option, la commande jstack, qui affichera la pile à partir de tout processus JDK6 en cours d'exécution sur votre ordinateur:

jstack [-l] <pid>

Ces options sont très utiles pour les applications qui s'exécutent dans un environnement de production et ne peuvent pas être modifiées facilement. Ils sont particulièrement utiles pour diagnostiquer les blocages d'exécution ou les problèmes de performance.

Http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/ http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html

6
répondu Andrew Newdigate 2009-06-03 16:04:38

Si vous avez besoin de la sortie de capture

StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
3
répondu Ricardo Jl Rufino 2017-04-04 10:50:27

Java 9 introduit le StackWalker et soutenir les classes pour marcher dans la pile.

Voici quelques extraits du Javadoc:

Le walk méthode ouvre un flux séquentiel de StackFrames pour le thread courant et applique ensuite la fonction donnée à pied de la StackFrame stream. Le flux rapporte les éléments de trame de pile dans l'ordre, à partir du cadre le plus haut qui représente le point d'exécution auquel la pile a été générée jusqu'au cadre le plus bas. Le StackFrame le flux est fermé lorsque la méthode walk revient. Si une tentative est faite pour réutiliser le flux fermé, IllegalStateException sera lancé.

...

  1. Pour capturer les 10 premières images de pile du thread courant,

    List<StackFrame> stack = StackWalker.getInstance().walk(s ->
     s.limit(10).collect(Collectors.toList()));
    
2
répondu mkobit 2017-12-07 14:16:03

HPROF Java Profiler

Vous n'avez même pas à le faire dans le code. Vous pouvez attacher le Java HPROF à votre processus et à tout moment appuyer sur Control - \ pour sortir le vidage du tas, exécuter des threads, etc. . . sans curage de votre code d'application. C'est un peu obsolète, Java 6 est livré avec l'interface graphique jconsole, mais je trouve toujours HPROF très utile.

0
répondu Gandalf 2017-05-30 15:00:28