Dalam istilah sederhana, jejak tumpukan adalah daftar metode panggilan bahwa aplikasi berada di tengah ketika Pengecualian dilemparkan.
Contoh sederhana
Dengan contoh yang diberikan dalam pertanyaan, kita dapat menentukan dengan tepat di mana pengecualian dilemparkan ke dalam aplikasi. Mari kita lihat jejak stack:
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)
Ini adalah jejak tumpukan yang sangat sederhana. Jika kita mulai dari awal daftar "at ...", kita dapat mengetahui di mana kesalahan kita terjadi. Yang kami cari adalah pemanggilan metode teratas yang merupakan bagian dari aplikasi kami. Dalam hal ini, ini:
at com.example.myproject.Book.getTitle(Book.java:16)
Untuk men-debug ini, kita dapat membuka Book.java
dan melihat baris 16
, yaitu:
15 public String getTitle() {
16 System.out.println(title.toString());
17 return title;
18 }
Ini akan menunjukkan bahwa sesuatu (mungkin title
) ada null
dalam kode di atas.
Contoh dengan rantai pengecualian
Terkadang aplikasi akan menangkap Pengecualian dan melemparkannya kembali sebagai penyebab Pengecualian lainnya. Ini biasanya terlihat seperti:
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 }
Ini mungkin memberi Anda jejak tumpukan yang terlihat seperti:
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
Yang berbeda dari yang satu ini adalah "Disebabkan oleh". Terkadang pengecualian memiliki beberapa bagian "Disebabkan oleh". Untuk ini, Anda biasanya ingin menemukan "akar penyebab", yang akan menjadi salah satu bagian "disebabkan oleh" terendah dalam jejak tumpukan. Dalam kasus kami, ini:
Caused by: java.lang.NullPointerException <-- root cause
at com.example.myproject.Book.getId(Book.java:22) <-- important line
Sekali lagi, dengan pengecualian ini kita ingin melihat garis 22
dari Book.java
untuk melihat apa yang mungkin menyebabkan NullPointerException
sini.
Contoh yang lebih menakutkan dengan kode perpustakaan
Biasanya jejak tumpukan jauh lebih kompleks daripada dua contoh di atas. Ini sebuah contoh (ini adalah contoh yang panjang, tetapi menunjukkan beberapa tingkat pengecualian berantai):
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
Dalam contoh ini, ada banyak lagi. Yang paling kami khawatirkan adalah mencari metode yang berasal dari kode kami , yang akan menjadi apa pun dalam com.example.myproject
paket. Dari contoh kedua (di atas), pertama-tama kita ingin melihat ke bawah untuk penyebab root, yaitu:
Caused by: java.sql.SQLException
Namun, semua panggilan metode di bawah itu adalah kode perpustakaan. Jadi kita akan naik ke "Disebabkan oleh" di atasnya, dan mencari pemanggilan metode pertama yang berasal dari kode kita, yaitu:
at com.example.myproject.MyEntityService.save(MyEntityService.java:59)
Seperti pada contoh sebelumnya, kita harus melihat secara MyEntityService.java
online 59
, karena di situlah kesalahan ini berasal (kesalahan ini agak jelas apa yang salah, karena SQLException menyatakan kesalahan, tetapi prosedur debug adalah yang kita kejar).