Einfach ausgedrückt, ein Stapelverfolgung ist eine Liste der Methodenaufrufe, in denen sich die Anwendung befand, als eine Exception ausgelöst wurde.
Einfaches Beispiel
Anhand des in der Frage genannten Beispiels können wir genau feststellen, wo die Ausnahme in der Anwendung ausgelöst wurde. Werfen wir einen Blick auf den Stack-Trace:
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)
Dies ist ein sehr einfacher Stack-Trace. Wenn wir am Anfang der Liste von "at ..." beginnen, können wir feststellen, wo der Fehler aufgetreten ist. Was wir suchen, ist die oberste Methodenaufruf, der Teil unserer Anwendung ist. In diesem Fall ist es:
at com.example.myproject.Book.getTitle(Book.java:16)
Um dies zu debuggen, können wir folgendes öffnen Book.java
und sehen Sie sich die Zeile 16
das ist:
15 public String getTitle() {
16 System.out.println(title.toString());
17 return title;
18 }
Dies würde bedeuten, dass etwas (wahrscheinlich title
) ist null
im obigen Code.
Beispiel mit einer Kette von Ausnahmen
Manchmal fangen Anwendungen eine Exception ab und werfen sie als Ursache einer anderen Exception wieder aus. Dies sieht typischerweise so aus:
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 }
Dies könnte einen Stack-Trace ergeben, der wie folgt aussieht:
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
Das Besondere an diesem Fall ist das "Verursacht durch". Manchmal haben Ausnahmen mehrere "Verursacht durch"-Abschnitte. In diesen Fällen wollen Sie in der Regel die "Hauptursache" finden, die einer der untersten "Verursacht durch"-Abschnitte im Stacktrace sein wird. In unserem Fall ist das:
Caused by: java.lang.NullPointerException <-- root cause
at com.example.myproject.Book.getId(Book.java:22) <-- important line
Auch bei dieser Ausnahme sollten wir uns die Zeile 22
von Book.java
um zu sehen, was die Ursache für die NullPointerException
hier.
Ein anspruchsvolleres Beispiel mit Bibliothekscode
Normalerweise sind Stack Traces viel komplexer als die beiden obigen Beispiele. Hier ist ein Beispiel (es ist lang, zeigt aber mehrere Ebenen von verketteten Ausnahmen):
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
In diesem Beispiel gibt es noch viel mehr. Worum es uns hauptsächlich geht, ist die Suche nach Methoden, die von unser Kodex was alles im Bereich der com.example.myproject
Paket. Im zweiten Beispiel (oben) würden wir zuerst nach der Grundursache suchen, die lautet:
Caused by: java.sql.SQLException
Alle Methodenaufrufe darunter sind jedoch Bibliothekscode. Wir werden also aufsteigen zum "Verursacht durch" oben und suchen Sie in diesem "Verursacht durch"-Block nach dem der erste Methodenaufruf, der aus unserem Code stammt das ist:
at com.example.myproject.MyEntityService.save(MyEntityService.java:59)
Wie in den vorangegangenen Beispielen sollten wir uns ansehen MyEntityService.java
im Netz 59
denn dort liegt der Ursprung des Fehlers (hier ist es etwas offensichtlich, was schief gelaufen ist, da die SQLException den Fehler angibt, aber wir wollen ja das Debugging-Verfahren).
34 Stimmen
Wenn eine Stacktrace-Zeile nicht den Dateinamen und eine Zeilennummer enthält, wurde die Klasse für diese Zeile nicht mit Debug-Informationen kompiliert.