774 votes

Ce qui est une trace de la pile, et comment puis-je l’utiliser pour déboguer mon Erreurs d’application ?

Parfois, quand je lance mon application, il me donne une erreur qui ressemble à ceci:

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 parlé comme d'une "trace de la pile". Qu'est ce qu'une trace de la pile? Que peut-il me dire à propos de l'erreur qui se passe dans mon programme?


À propos de cette question assez souvent, je vois une question de grâce où un programmeur novice est "une erreur", et ils suffit de coller leur trace de la pile et du hasard bloc de code sans comprendre ce que la trace de la pile est ou comment ils peuvent l'utiliser. Cette question se veut une référence pour les programmeurs débutants qui pourraient avoir besoin d'aide pour comprendre la valeur d'une trace de la pile.

733voto

Rob Hruska Points 39151

En termes simples, une trace de la pile est une liste des appels de méthode que la demande a été dans le milieu d'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 coup d'oeil à 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)

C'est très simple trace de la pile. Si nous commençons au début de la liste des "à ...", nous pouvons déterminer où l'erreur s'est produite. Ce que nous recherchons est le premier appel de la méthode dans le cadre de notre application. Dans ce cas, c'est:

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

Pour déboguer cela, nous pouvons ouvrir l' Book.java regardez à la ligne 16, qui est:

public String getTitle() {
    System.out.println(title.toString()); <-- line 16
    return title;
}

Cela semble indiquer que quelque chose (probablement title) null dans le code ci-dessus.

Exemple avec une chaîne d'exceptions

Parfois les applications de capture d'une Exception et de renvoyer la cause d'une autre Exception. Généralement, cela ressemble:

try {
....
} catch (NullPointerException e) {
  throw new IllegalStateException("A book has a null property", e)
}

Cela peut vous donner une trace de la pile qui ressemble à ceci:

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:35)
        ... 1 more

Ce qui est différent c'est le plus "Causé par". Parfois des exceptions aura de multiples "Causé par" sections. Pour ces derniers, vous souhaitez généralement de trouver la "root cause", qui sera l'un des plus faibles "Causé par" les articles 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 que nous voudrions, regardez à la ligne 22 de Book.java pour voir ce qui pourrait provoquer l' NullPointerException ici.

De plus en plus décourageant exemple avec code de bibliothèque

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

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 que nous sommes surtout préoccupés par est à la recherche pour les méthodes qui sont de notre code, ce qui serait quelque chose dans l' com.example.myproject package. À partir du deuxième exemple (ci-dessus), nous devons d'abord regarder vers le bas pour la cause, qui est:

Caused by: java.sql.SQLException

Cependant, tous les appels de méthode de vertu que sont le code de bibliothèque. Donc, nous allons passer à la "Causé par" au-dessus d'elle, et de regarder pour le premier appel de la méthode en provenance de notre code, qui est:

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

Comme dans les exemples précédents, nous devrions examiner MyEntityService.java en ligne 59, parce que cette erreur provient (celui-ci est un peu évident que ce qui s'est passé, depuis la SQLException membres de l'erreur, mais la procédure de débogage est ce que nous sommes après).

24voto

Woot4Moo Points 14245

Pour ajouter à ce que Rob a mentionné. Réglage des points de rupture dans votre application permet pour l'étape-par-étape du traitement de la pile. Cela permet au développeur d'utiliser le débogueur de voir à quel point exact de la méthode est quelque chose qui a été anticipés.

Depuis 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 voulons évaluer le prénom contient une valeur, nous voudrions le faire comme ceci: if(firstName == null || firstName.equals("")) return;

Le ci-dessus ne nous empêche de les utiliser prénom comme un dangereux paramètre. Donc en faisant null vérifications avant la transformation, nous pouvons contribuer à ce que notre code s'exécute correctement. Pour se développer sur un exemple qui utilise un objet avec des méthodes que nous pouvons voir ici:

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

Le ci-dessus est la bonne pour vérifier les valeurs null, nous commençons avec l'objet de base, le chien dans ce cas, et puis commencer à marcher vers le bas de l'arbre des possibles pour s'assurer que tout est valide avant le traitement. Si la commande a été inversée un NPE pourrait être jetés et notre programme crash.

19voto

przemek hertel Points 995

Il existe une fonctionnalité de stacktrace plus offerte par la famille Throwable - la possibilité de manipuler des informations de trace de pile.

Comportement standard :

Trace de la pile :

Trace de la pile manipulé :

Trace de la pile :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X