Qu'est-ce qu'une trace de pile et comment puis-je l'utiliser pour déboguer mes erreurs d'application?

643

Parfois, lorsque j'exécute mon application, cela me donne une erreur qui ressemble à:

Exception in thread "main" java.lang.NullPointerException
        at com.example.myproject.Book.getTitle(Book.java:16)
        at com.example.myproject.Author.getBookTitles(Author.java:25)
        at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Les gens ont appelé cela une "trace de pile". Qu'est-ce qu'une trace de pile? Que peut-il me dire sur l'erreur qui se produit dans mon programme?


À propos de cette question - très souvent, je vois une question surgir par laquelle un programmeur novice "obtient une erreur", et il colle simplement sa trace de pile et un bloc de code aléatoire sans comprendre ce qu'est la trace de pile ou comment il peut l'utiliser. Cette question est conçue comme une référence pour les programmeurs débutants qui pourraient avoir besoin d'aide pour comprendre la valeur d'une trace de pile.

Rob Hruska
la source
25
De plus, si une ligne stacktrace ne contient pas le nom de fichier et un numéro de ligne, la classe de cette ligne n'a pas été compilée avec les informations de débogage.
Thorbjørn Ravn Andersen

Réponses:

590

En termes simples, une trace de pile est une liste des appels de méthode que l'application était au milieu lorsqu'une exception a été levée.

Exemple simple

Avec l'exemple donné dans la question, nous pouvons déterminer exactement où l'exception a été levée dans l'application. Jetons un œil à la trace de la pile:

Exception in thread "main" java.lang.NullPointerException
        at com.example.myproject.Book.getTitle(Book.java:16)
        at com.example.myproject.Author.getBookTitles(Author.java:25)
        at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Il s'agit d'une trace de pile très simple. Si nous commençons au début de la liste des "à ...", nous pouvons dire où s'est produite notre erreur. Ce que nous recherchons, c'est l' appel de méthode le plus haut qui fait partie de notre application. Dans ce cas, c'est:

at com.example.myproject.Book.getTitle(Book.java:16)

Pour déboguer cela, nous pouvons ouvrir Book.javaet regarder la ligne 16, qui est:

15   public String getTitle() {
16      System.out.println(title.toString());
17      return title;
18   }

Cela indiquerait que quelque chose (probablement title) se trouve nulldans le code ci-dessus.

Exemple avec une chaîne d'exceptions

Parfois, les applications interceptent une exception et la rejettent comme cause d'une autre exception. Cela ressemble généralement à:

34   public void getBookIds(int id) {
35      try {
36         book.getId(id);    // this method it throws a NullPointerException on line 22
37      } catch (NullPointerException e) {
38         throw new IllegalStateException("A book has a null property", e)
39      }
40   }

Cela pourrait vous donner une trace de pile qui ressemble à:

Exception in thread "main" java.lang.IllegalStateException: A book has a null property
        at com.example.myproject.Author.getBookIds(Author.java:38)
        at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Caused by: java.lang.NullPointerException
        at com.example.myproject.Book.getId(Book.java:22)
        at com.example.myproject.Author.getBookIds(Author.java:36)
        ... 1 more

Ce qui est différent dans celui-ci, c'est le "Causé par". Parfois, les exceptions auront plusieurs sections "Causées par". Pour ceux-ci, vous voulez généralement trouver la «cause racine», qui sera l'une des sections «Causées par» les plus basses dans la trace de la pile. Dans notre cas, c'est:

Caused by: java.lang.NullPointerException <-- root cause
        at com.example.myproject.Book.getId(Book.java:22) <-- important line

Encore une fois, avec cette exception, nous voudrions regarder la ligne 22de Book.javapour voir ce qui pourrait provoquer NullPointerExceptionici.

Exemple plus intimidant avec le code de bibliothèque

Habituellement, les traces de pile sont beaucoup plus complexes que les deux exemples ci-dessus. Voici un exemple (il est long, mais montre plusieurs niveaux d'exceptions chaînées):

javax.servlet.ServletException: Something bad happened
    at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:60)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.example.myproject.ExceptionHandlerFilter.doFilter(ExceptionHandlerFilter.java:28)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.example.myproject.OutputBufferFilter.doFilter(OutputBufferFilter.java:33)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
Caused by: com.example.myproject.MyProjectServletException
    at com.example.myproject.MyServlet.doPost(MyServlet.java:169)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
    at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:30)
    ... 27 more
Caused by: org.hibernate.exception.ConstraintViolationException: could not insert: [com.example.myproject.MyEntity]
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:64)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2329)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2822)
    at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:268)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:321)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
    at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
    at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:705)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:693)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:689)
    at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:344)
    at $Proxy19.save(Unknown Source)
    at com.example.myproject.MyEntityService.save(MyEntityService.java:59) <-- relevant call (see notes below)
    at com.example.myproject.MyServlet.doPost(MyServlet.java:164)
    ... 32 more
Caused by: java.sql.SQLException: Violation of unique constraint MY_ENTITY_UK_1: duplicate value(s) for column(s) MY_COLUMN in statement [...]
    at org.hsqldb.jdbc.Util.throwError(Unknown Source)
    at org.hsqldb.jdbc.jdbcPreparedStatement.executeUpdate(Unknown Source)
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
    at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:57)
    ... 54 more

Dans cet exemple, il y en a beaucoup plus. Ce qui nous préoccupe le plus, c'est la recherche de méthodes qui proviennent de notre code , qui seraient n'importe quoi dans le com.example.myprojectpackage. Dans le deuxième exemple (ci-dessus), nous voudrions d'abord regarder vers le bas pour la cause racine, qui est:

Caused by: java.sql.SQLException

Cependant, tous les appels de méthode sous ce code sont de la bibliothèque. Nous allons donc passer au "Causé par" au-dessus, et chercher le premier appel de méthode provenant de notre code, qui est:

at com.example.myproject.MyEntityService.save(MyEntityService.java:59)

Comme dans les exemples précédents, nous devrions regarder en MyEntityService.javaligne 59, car c'est de là que cette erreur est originaire (celle-ci est un peu évidente ce qui s'est mal passé, car la SQLException indique l'erreur, mais la procédure de débogage est ce que nous recherchons).

Rob Hruska
la source
3
@RobHruska - Très bien expliqué. +1. Connaissez-vous des analyseurs qui prennent la trace d'exception sous forme de chaîne et fournissent des méthodes utiles pour analyser la trace de pile? - comme getLastCausedBy () ou getCausedByForMyAppCode ("com.example.myproject")
Andy Dufresne
1
@AndyDufresne - Je n'en ai rencontré aucun, mais là encore je n'ai pas vraiment regardé non plus.
Rob Hruska
1
Amélioration suggérée: expliquez la première ligne d'une trace de pile qui commence par Exception in thread "main"dans votre premier exemple. Je pense qu'il serait particulièrement utile d'expliquer que cette ligne est souvent accompagnée d'un message, comme la valeur d'une variable, qui peut aider à diagnostiquer le problème. J'ai essayé de faire une modification moi-même, mais j'ai du mal à intégrer ces idées dans la structure existante de votre réponse.
Code-Apprentice
5
Java 1.7 a également ajouté "Supprimé:" - qui répertorie les traces de pile d'exceptions supprimées avant d'afficher "Causé par:" pour cette exception. Il est automatiquement utilisé par la construction try-with-resource: docs.oracle.com/javase/specs/jls/se8/html/… et contient des exceptions, le cas échéant, qui ont été levées lors de la fermeture des ressources.
dhblah
Il existe un JEP openjdk.java.net/jeps/8220715 qui vise à améliorer davantage la compréhensibilité des NPE en particulier en fournissant des détails tels que "Impossible d'écrire le champ 'nullInstanceField' parce que 'this.nullInstanceField' est null."
Mahatma_Fatal_Error
80

Je poste cette réponse, donc la réponse la plus élevée (lorsqu'elle est triée par activité) n'est pas celle qui est tout simplement fausse.

Qu'est-ce qu'un Stacktrace?

Un stacktrace est un outil de débogage très utile. Il montre la pile d'appels (c'est-à-dire la pile de fonctions qui ont été appelées jusqu'à ce point) au moment où une exception non interceptée a été levée (ou au moment où la trace de pile a été générée manuellement). Ceci est très utile car il vous montre non seulement où l'erreur s'est produite, mais aussi comment le programme s'est retrouvé à cet endroit du code. Cela nous amène à la question suivante:

Qu'est-ce qu'une exception?

Une exception est ce que l'environnement d'exécution utilise pour vous indiquer qu'une erreur s'est produite. Des exemples populaires sont NullPointerException, IndexOutOfBoundsException ou ArithmeticException. Chacun de ces problèmes survient lorsque vous essayez de faire quelque chose qui n'est pas possible. Par exemple, une NullPointerException sera levée lorsque vous essayez de déréférencer un objet Null:

Object a = null;
a.toString();                 //this line throws a NullPointerException

Object[] b = new Object[5];
System.out.println(b[10]);    //this line throws an IndexOutOfBoundsException,
                              //because b is only 5 elements long
int ia = 5;
int ib = 0;
ia = ia/ib;                   //this line throws an  ArithmeticException with the 
                              //message "/ by 0", because you are trying to
                              //divide by 0, which is not possible.

Comment dois-je gérer les Stacktraces / Exceptions?

Dans un premier temps, découvrez ce qui cause l'exception. Essayez de rechercher sur Google le nom de l'exception pour savoir quelle est la cause de cette exception. La plupart du temps, cela sera dû à un code incorrect. Dans les exemples ci-dessus, toutes les exceptions sont causées par un code incorrect. Donc, pour l'exemple NullPointerException, vous pouvez vous assurer que ce an'est jamais nul à ce moment-là. Vous pouvez, par exemple, initialiser aou inclure un chèque comme celui-ci:

if (a!=null) {
    a.toString();
}

De cette façon, la ligne incriminée n'est pas exécutée si a==null. Il en va de même pour les autres exemples.

Parfois, vous ne pouvez pas vous assurer de ne pas obtenir d'exception. Par exemple, si vous utilisez une connexion réseau dans votre programme, vous ne pouvez pas empêcher l'ordinateur de perdre sa connexion Internet (par exemple, vous ne pouvez pas empêcher l'utilisateur de déconnecter la connexion réseau de l'ordinateur). Dans ce cas, la bibliothèque réseau lèvera probablement une exception. Vous devez maintenant intercepter l'exception et la gérer . Cela signifie que, dans l'exemple avec la connexion réseau, vous devez essayer de rouvrir la connexion ou avertir l'utilisateur ou quelque chose comme ça. De plus, chaque fois que vous utilisez catch, n'attrapez toujours que l'exception que vous souhaitez intercepter, n'utilisez pas de déclarations catch larges commecatch (Exception e)cela intercepterait toutes les exceptions. Ceci est très important, car sinon vous pourriez accidentellement attraper la mauvaise exception et réagir de la mauvaise manière.

try {
    Socket x = new Socket("1.1.1.1", 6789);
    x.getInputStream().read()
} catch (IOException e) {
    System.err.println("Connection could not be established, please try again later!")
}

Pourquoi ne devrais-je pas utiliser catch (Exception e)?

Prenons un petit exemple pour montrer pourquoi vous ne devriez pas simplement intercepter toutes les exceptions:

int mult(Integer a,Integer b) {
    try {
        int result = a/b
        return result;
    } catch (Exception e) {
        System.err.println("Error: Division by zero!");
        return 0;
    }
}

Ce que ce code essaie de faire est d'attraper le ArithmeticExceptioncausé par une division possible par 0. Mais il attrape également un possible NullPointerExceptionqui est levé si aou bsont null. Cela signifie que vous pourriez en avoir un NullPointerExceptionmais vous le traiterez comme une ArithmeticException et vous ferez probablement la mauvaise chose. Dans le meilleur des cas, il vous manque toujours une exception NullPointerException. Des trucs comme ça rendent le débogage beaucoup plus difficile, alors ne faites pas ça.

TLDR

  1. Déterminez quelle est la cause de l'exception et corrigez-la, afin qu'elle ne lève pas du tout l'exception.
  2. Si 1. n'est pas possible, interceptez l'exception spécifique et gérez-la.

    • N'ajoutez jamais un try / catch puis ignorez l'exception! Ne fais pas ça!
    • Ne jamais utiliser catch (Exception e), toujours attraper des exceptions spécifiques. Cela vous évitera beaucoup de maux de tête.
Dakkaron
la source
1
belle explication pour pourquoi nous devrions éviter le masquage de bogues
Sudip Bhandari
2
Je poste cette réponse, donc la réponse la plus élevée (lorsqu'elle est triée par activité) n'est pas celle qui est tout simplement erronée.Je n'ai aucune idée de celle dont vous parlez car cela a probablement changé à ce jour. Mais la réponse acceptée est définitivement plus intéressante;)
AxelH
1
Pour autant que je sache, celui que je voulais dire a été supprimé. Il a simplement dit "juste mettre un essai {} catch (Exception e) {} et ignorer toutes les erreurs". La réponse acceptée est beaucoup plus ancienne que ma réponse, donc je visais à donner un peu un avis différent sur la question. Je ne pense pas que cela aide quelqu'un à simplement copier la réponse de quelqu'un d'autre ou à couvrir ce que d'autres personnes ont déjà bien couvert.
Dakkaron
Il est trompeur de dire "Ne pas attraper d'exception", ce n'est qu'un cas d'utilisation. Votre exemple est génial, mais qu'en est-il de votre position en haut de votre boucle de threads (à l'intérieur de la course)? Vous devez TOUJOURS intercepter l'exception (ou peut-être Throwable) et la journaliser afin qu'elle ne disparaisse pas de manière invisible (les exceptions levées lors de l'exécution ne sont généralement pas enregistrées correctement sauf si vous avez configuré votre thread / enregistreur pour le faire).
Bill K
1
Je n'ai pas inclus ce cas spécial car il ne concerne que le multithreading. Dans le thread unique, une exception qui a fui tue le programme et est enregistrée de manière visible. Si quelqu'un ne sait pas comment gérer correctement les exceptions, il ne sait généralement pas encore comment utiliser le multithreading.
Dakkaron
21

Pour ajouter à ce que Rob a mentionné. La définition de points d'arrêt dans votre application permet le traitement pas à pas de la pile. Cela permet au développeur d'utiliser le débogueur pour voir à quel point exact la méthode fait quelque chose d'imprévu.

Étant donné que Rob a utilisé le NullPointerException(NPE) pour illustrer quelque chose de commun, nous pouvons vous aider à supprimer ce problème de la manière suivante:

si nous avons une méthode qui prend des paramètres tels que: void (String firstName)

Dans notre code, nous voudrions évaluer qui firstNamecontient une valeur, nous le ferions comme ceci:if(firstName == null || firstName.equals("")) return;

Ce qui précède nous empêche d'utiliser firstNamecomme paramètre dangereux. Par conséquent, en effectuant des vérifications nulles avant le traitement, nous pouvons nous assurer que notre code fonctionnera correctement. Pour développer un exemple qui utilise un objet avec des méthodes, nous pouvons regarder ici:

if(dog == null || dog.firstName == null) return;

Ce qui précède est l'ordre approprié pour vérifier les valeurs nulles, nous commençons par l'objet de base, chien dans ce cas, puis commençons à descendre l'arborescence des possibilités pour nous assurer que tout est valide avant le traitement. Si l'ordre était inversé, un NPE pourrait potentiellement être lancé et notre programme se bloquerait.

Woot4Moo
la source
D'accord. Cette approche pourrait être utilisée pour trouver quelle référence dans une déclaration est nullquand un NullPointerExceptionest en cours d'examen, par exemple.
Rob Hruska
16
Lorsque vous traitez avec String, si vous voulez utiliser la méthode equals, je pense qu'il vaut mieux utiliser la constante dans le côté gauche de la comparaison, comme ceci: Au lieu de: if (firstName == null || firstName.equals ("" )) revenir; J'utilise toujours: if ((""). Equals (firstName)) Cela empêche l'exception Nullpointer
Torres
15

La famille Throwable offre une autre fonctionnalité de trace de pile : la possibilité de manipuler les informations de trace de pile.

Comportement standard:

package test.stack.trace;

public class SomeClass {

    public void methodA() {
        methodB();
    }

    public void methodB() {
        methodC();
    }

    public void methodC() {
        throw new RuntimeException();
    }

    public static void main(String[] args) {
        new SomeClass().methodA();
    }
}

Trace de la pile:

Exception in thread "main" java.lang.RuntimeException
    at test.stack.trace.SomeClass.methodC(SomeClass.java:18)
    at test.stack.trace.SomeClass.methodB(SomeClass.java:13)
    at test.stack.trace.SomeClass.methodA(SomeClass.java:9)
    at test.stack.trace.SomeClass.main(SomeClass.java:27)

Trace de pile manipulée:

package test.stack.trace;

public class SomeClass {

    ...

    public void methodC() {
        RuntimeException e = new RuntimeException();
        e.setStackTrace(new StackTraceElement[]{
                new StackTraceElement("OtherClass", "methodX", "String.java", 99),
                new StackTraceElement("OtherClass", "methodY", "String.java", 55)
        });
        throw e;
    }

    public static void main(String[] args) {
        new SomeClass().methodA();
    }
}

Trace de la pile:

Exception in thread "main" java.lang.RuntimeException
    at OtherClass.methodX(String.java:99)
    at OtherClass.methodY(String.java:55)
przemek hertel
la source
2
Je ne sais pas ce que je ressens à ce sujet ... avec la nature du thread, je conseillerais aux nouveaux développeurs de ne pas définir leur propre trace de pile.
PeonProgrammer
15

Pour comprendre le nom : Une trace de pile est une liste d'exceptions (ou vous pouvez dire une liste de "cause par"), de l'exception la plus superficielle (par exemple, exception de couche de service) à la plus profonde (par exemple exception de base de données). Tout comme la raison pour laquelle nous l'appelons `` pile '' est parce que la pile est First in Last out (FILO), l'exception la plus profonde s'est produite au tout début, puis une chaîne d'exceptions a été générée une série de conséquences, l'exception de surface était la dernière on est arrivé à temps, mais on le voit en premier lieu.

Clé 1 : Une chose délicate et importante ici doit être comprise: la cause la plus profonde peut ne pas être la "cause racine", car si vous écrivez du "mauvais code", cela peut provoquer une exception en dessous qui est plus profonde que sa couche. Par exemple, une mauvaise requête SQL peut entraîner une réinitialisation de la connexion SQLServerException dans le bottem au lieu d'une erreur syndax, qui peut se trouver juste au milieu de la pile.

-> Localiser la cause première au milieu est votre travail. entrez la description de l'image ici

Clé 2 : Une autre chose délicate mais importante est à l'intérieur de chaque bloc "Cause par", la première ligne était la couche la plus profonde et arrive en première place pour ce bloc. Par exemple,

Exception in thread "main" java.lang.NullPointerException
        at com.example.myproject.Book.getTitle(Book.java:16)
           at com.example.myproject.Author.getBookTitles(Author.java:25)
               at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Book.java:16 a été appelé par Auther.java:25 qui a été appelé par Bootstrap.java:14, Book.java:16 en était la cause première. Ci-joint un diagramme qui trie la pile de trace dans l'ordre chronologique. entrez la description de l'image ici

Kevin Li
la source
8

Juste pour ajouter aux autres exemples, il existe des classes internes (imbriquées) qui apparaissent avec le $signe. Par exemple:

public class Test {

    private static void privateMethod() {
        throw new RuntimeException();
    }

    public static void main(String[] args) throws Exception {
        Runnable runnable = new Runnable() {
            @Override public void run() {
                privateMethod();
            }
        };
        runnable.run();
    }
}

Entraînera cette trace de pile:

Exception in thread "main" java.lang.RuntimeException
        at Test.privateMethod(Test.java:4)
        at Test.access$000(Test.java:1)
        at Test$1.run(Test.java:10)
        at Test.main(Test.java:13)
Eugene S
la source
5

Les autres articles décrivent ce qu'est une trace de pile, mais il peut toujours être difficile de travailler avec.

Si vous obtenez une trace de pile et souhaitez rechercher la cause de l'exception, un bon point de départ pour la comprendre est d'utiliser la console de trace de pile Java dans Eclipse . Si vous utilisez un autre IDE, il peut y avoir une fonctionnalité similaire, mais cette réponse concerne Eclipse.

Tout d'abord, assurez-vous que toutes vos sources Java sont accessibles dans un projet Eclipse.

Ensuite, dans la perspective Java , cliquez sur l' onglet Console (généralement en bas). Si la vue de la console n'est pas visible, accédez à l'option de menu Fenêtre -> Afficher la vue et sélectionnez Console .

Puis dans la fenêtre de la console, cliquez sur le bouton suivant (à droite)

Bouton Consoles

puis sélectionnez Java Stack Trace Console dans la liste déroulante.

Collez votre trace de pile dans la console. Il fournira ensuite une liste de liens vers votre code source et tout autre code source disponible.

Voici ce que vous pourriez voir (image de la documentation Eclipse):

Diagramme de la documentation Eclipse

L'appel de méthode le plus récent sera le haut de la pile, qui est la première ligne (à l'exclusion du texte du message). Descendre la pile remonte dans le temps. La deuxième ligne est la méthode qui appelle la première ligne, etc.

Si vous utilisez un logiciel open source, vous devrez peut-être télécharger et joindre à votre projet les sources si vous souhaitez les examiner. Téléchargez les fichiers source, dans votre projet, ouvrez le dossier Bibliothèques référencées pour trouver votre fichier pour votre module open-source (celui avec les fichiers de classe) puis cliquez avec le bouton droit, sélectionnez Propriétés et attachez le fichier source.

rghome
la source