Question

Je souhaite écrire une visualisation simple d'un programme Java en affichant les appels de méthode du programme sous forme de branches d'un arbre. Cela pourrait être fait simplement en laissant le programme lui-même indiquer à la visualisation ce qu'il fait, mais je veux pouvoir le faire avec n'importe quelle méthode / classe Java et pas seulement avec celles que je modifie pour le faire.

Ce dont j'ai besoin, c'est de pouvoir regarder les méthodes appelées par un programme et quelles méthodes sont appelées au sein de cette méthode, etc. Évidemment, les traces de pile fournissent exactement cette fonctionnalité:

 java.lang.NullPointerException
     at MyClass.mash(MyClass.java:9)
     at MyClass.crunch(MyClass.java:6)
     at MyClass.main(MyClass.java:3)

J'ai donc pensé à exécuter le programme que je veux surveiller dans un thread, puis à regarder simplement la pile de ce thread. Cependant, la classe de thread ne supporte pas vraiment cela. Il ne supporte que l’impression de la pile actuelle.

Maintenant, bien sûr, j'ai pensé changer simplement le flux d'impression PrintStream de la classe System afin que le thread imprime sa pile dans mon PrintStream, mais cela semble un peu faux.

Y a-t-il une meilleure façon de faire cela? Existe-t-il des classes / méthodes préexistantes que je peux utiliser?

De plus, je suis en train de télécharger le code source Java pour vérifier comment la classe de thread imprime exactement sa pile pour pouvoir peut-être sous-classer un thread et imiter la méthode dumpStack () avec ma propre méthode getStack ().

Était-ce utile?

La solution 2

Oh shoot, en parcourant le code source, j'ai remarqué que la classe thread avait une méthode publique StackTraceElement [] getStackTrace (), ce n'était tout simplement pas dans la documentation que je lisais. Maintenant, je me sens bête.

Alors oui, cela semble être la solution.

Autres conseils

Regardez également VisualVM, livré avec les dernières versions de Java.

Une approche pourrait consister à utiliser quelque chose comme BCEL pour prétraiter le bytecode cible dans lequel insérer des appels. votre propre code sur chaque entrée et sortie de méthode (il est probablement préférable de fermer en encapsulant toute la méthode dans un bloc try / finally, pour intercepter les exits d'exception). Vous pouvez en déduire l’arbre des appels exactement comme il se passe.

Vous pouvez utiliser AspectJ pour cela. Jetez un coup d’œil à cette description d'exactement votre cas d'utilisation.

Consultez la classe ThreadMXBean . vous avez besoin. Essentiellement, vous:

  • appelez ManagementFactory.getThreadMXBean () pour obtenir une instance de ThreadMXBean;
  • appelez getAllThreadIds () sur le ThreadMXBean résultant pour énumérer les threads actuels;
  • appelez getThreadInfo () pour obtenir les n premiers éléments de trace de pile dans une liste de threads donnée.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top