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.
9 réponses
Vous pouvez également essayer Thread.getAllStackTraces()
pour obtenir une carte des traces de pile pour tous les threads qui sont vivants.
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.
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.
Notez ce fil.dumpStack() lance une exception:
new Exception("Stack trace").printStackTrace();
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
Si vous avez besoin de la sortie de capture
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
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 deStackFrames
pour le thread courant et applique ensuite la fonction donnée à pied de laStackFrame
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. LeStackFrame
le flux est fermé lorsque la méthode walk revient. Si une tentative est faite pour réutiliser le flux fermé,IllegalStateException
sera lancé....
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()));
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.