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 générer d’exception?
Mon objectif est de, dans une méthode donnée, vider une pile pour voir qui est l'appelant de la méthode.
Vous pouvez également essayer Thread.getAllStackTraces()
pour obtenir une carte des traces de pile pour tous les threads en vie.
Oui, utilisez simplement
Thread.dumpStack()
Si vous souhaitez que la trace ne concerne que le thread actuel (plutôt que tous les threads du système, comme le suggère Ram), faites:
Thread.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. Toutefois, un mot d'avertissement: l'index du cadre d'appel dans la liste peut varier en fonction de la JVM! Tout dépend du nombre d'appels qu'il y a dans getStackTrace avant que vous atteigniez le point où la trace est générée. Une solution plus robuste consisterait à obtenir la trace et à la parcourir en recherchant le cadre pour getCallingMethodName, puis à franchir deux étapes supplémentaires pour rechercher le véritable appelant.
Vous pouvez obtenir une trace de pile comme ceci:
Throwable t = new Throwable();
t.printStackTrace();
Si vous souhaitez accéder au cadre, vous pouvez utiliser t.getStackTrace () pour obtenir un tableau de cadres de pile.
Sachez que certaines images peuvent manquer à ce stacktrace si le compilateur de hotspot a été occupé à optimiser les choses.
Notez que Thread.dumpStack () lève réellement une exception:
new Exception("Stack trace").printStackTrace();
Vous pouvez également envoyer un signal à la machine virtuelle Java pour qu'il exécute Thread.getAllStackTraces () sur un processus en cours d'exécution Java) en envoyant un signal QUIT au processus.
Sous Unix/Linux, utilisez:
kill -QUIT process_id
, où id_processus est le numéro de processus de votre programme Java.
Sous Windows, vous pouvez appuyer sur Ctrl-Pause dans l'application, bien que vous ne le voyiez généralement pas à moins que vous n'exécutiez un processus de console.
JDK6 a introduit une autre option, la commande jstack, qui affiche la pile 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 performances.
http://Java.Sun.com/developer/technicalArticles/Programming/Stacktrace/http://Java.Sun.com/javase/6/docs/technotes/tools/share /jstack.html
Java 9 a introduit StackWalker
et les classes de support permettant de parcourir la pile.
Voici quelques extraits de la Javadoc:
La méthode
walk
ouvre un flux séquentiel deStackFrames
pour le thread actuel, puis applique la fonction donnée pour parcourir leStackFrame
flux. Le flux rapporte les éléments du cadre de pile dans l'ordre, du cadre le plus haut qui représente le point d'exécution auquel la pile a été générée au cadre le plus bas. Le fluxStackFrame
est fermé au retour de la méthode walk. Si l'on tente de réutiliser le flux fermé,IllegalStateException
sera lancé....
Pour capturer les 10 meilleurs cadres de la pile du fil actuel,
List<StackFrame> stack = StackWalker.getInstance().walk(s -> s.limit(10).collect(Collectors.toList()));
Si vous avez besoin d'une sortie de capture
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
Vous n'avez même pas à faire cela dans le code. Vous pouvez attacher le Java HPROF à votre processus et appuyer à tout moment sur Ctrl-\pour générer le vidage de segment de mémoire, les threads en cours d'exécution, etc.) sans modifier le code de votre application. C'est un peu obsolète. , Java 6 est livré avec l’interface graphique jconsole, mais je trouve toujours HPROF très utile.