什么是堆栈跟踪,如何使用它来调试我的应用程序错误? [英] What is a stack trace, and how can I use it to debug my application errors?

查看:121
本文介绍了什么是堆栈跟踪,如何使用它来调试我的应用程序错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时,当我运行我的应用程序时,它给我一个错误,看起来像:

 线程mainjava中的异常。 lang.NullPointerException 
在com.example.myproject.Book.getTitle(Book.java:16)
在com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

人们已经提到这个作为堆栈跟踪。 什么是堆栈跟踪?可以告诉我有关我节目中发生的错误?





$ b $关于这个问题 - 很多时候,我看到一个问题来自于一个新手程序员得到一个错误,他们只是粘贴他们的堆栈跟踪和一些随机的代码块,而不了解堆栈跟踪是什么或者他们如何使用它。这个问题是作为一个可能需要帮助了解堆栈跟踪的值的新手程序员的参考。

解决方案

简单来说,堆栈跟踪是应用程序在抛出异常时的方法调用列表。



简单示例



通过问题中给出的示例,我们可以确定应用程序中抛出异常的位置。我们来看看堆栈跟踪:

 线程main中的异常java.lang.NullPointerException 
at com .example.myproject.Book.getTitle(Book.java:16)
在com.example.myproject.Author.getBookTitles(Author.java:25)
在com.example.myproject.Bootstrap.main (Bootstrap.java:14)

这是一个非常简单的堆栈跟踪。如果我们从at ...列表的开头开始,我们可以知道错误发生在哪里。我们正在寻找的是作为我们应用程序一部分的最上层方法调用。在这种情况下,它是:

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

要进行调试,我们可以打开 Book.java 并查看 16 ,这是:

  15 public String getTitle (){
16 System.out.println(title.toString());
17返回标题;
18}

这将表明某事(可能 title )是上述代码中的 null



例外



有时,应用程序将捕获异常并将其重新抛出,作为另一个异常的原因。这通常看起来像:

  34 public void getBookIds(int id){
35 try {
36 book.getId(id); //这个方法在第22行抛出一个NullPointerException
37} catch(NullPointerException e){
38 throw new IllegalStateException(A book has a null property,e)
39}
40}

这可能会给你一个堆栈跟踪,如下所示:

 线程main中的异常java.lang.IllegalStateException:一本书在com.example.myproject.Author中有一个空属性
。 getBookIds(Author.java:38)
在com.example.myproject.Bootstrap.main(Bootstrap.java:14)
导致:java.lang.NullPointerException com.example中的
。 myproject.Book.getId(Book.java:22)
在com.example.myproject.Author.getBookIds(Author.java:36)
... 1更多

这个是Caused by的区别。有时例外会有多个由...导致部分。对于这些,您通常需要找到根本原因,这将是堆栈跟踪中最低的导致部分之一。在我们的例子中,它是:

 导致:java.lang.NullPointerException<  - 根本原因
.example.myproject.Book.getId(Book.java:22)< - 重要行

再次,有了这个例外,我们想看看 22 Book.java ,看看可能会导致什么 NullPointerException 这里。



使用库代码更加令人生畏的例子



通常堆栈跟踪比上述两个例子复杂得多。这是一个例子(这是一个很长的例子,但是演示了几个级别的链接异常):

  javax.servlet.ServletException:发生在
com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:60)
在org.mortbay.jetty.servlet.ServletHandler $ CachedChain.doFilter(ServletHandler.java:1157)
com.example.myproject.ExceptionHandlerFilter.doFilter(ExceptionHandlerFilter.java:28)
在org.mortbay.jetty.servlet.ServletHandler $ CachedChain.doFilter(ServletHandler.java:1157)
在com。 example.myproject.OutputBufferFilter.doFilter(OutputBufferFilter.java:33)
在org.mortbay.jetty.servlet.ServletHandler $ CachedChain.doFilter(ServletHandler.java:1157)
在org.mortbay.jetty。 servlet.ServletHandler.handle(ServletHandler.java:388)
在org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
在org.mortbay.jetty.servlet.SessionHandler。把手(S essionHandler.java:182)
在org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
在org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java: 418)
在org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
在org.mortbay.jetty.Server.handle(Server.java:326)
在org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
在org.mortbay.jetty.HttpConnection $ RequestHandler.content(HttpConnection.java:943)
在org.mortbay.jetty .HttpParser.parseNext(HttpParser.java:756)
在org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
在org.mortbay.jetty.HttpConnection.handle(HttpConnection.java :404)
在org.mortbay.jetty.bio.SocketConnector $ Connection.run(SocketConnector.java:228)
在org.mortbay.thread.QueuedThreadPool $ PoolThread.run(QueuedThreadPool.java:582 )
导致:com.example.myproject.MyProjectServletException
at com .example.myproject.MyServlet.doPost(MyServlet.java:169)
在javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
在javax.servlet.http.HttpServlet.service (HttpServlet.java:820)
在org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
在org.mortbay.jetty.servlet.ServletHandler $ CachedChain.doFilter(ServletHandler .java:1166)
在com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:30)
... 27更多
导致:org.hibernate.exception.ConstraintViolationException:无法插入:[com.example.myproject.MyEntity]
在org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
在org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper .java:66)
在org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:64)
在org.hibernate.persister.entity.AbstractEntityPersister.insert(Abstra ctEntityPersister.java:2329)
在org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2822)
在org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71)
在org.hibernate.engine.ActionQueue.execute(ActionQueue.java:268)
在org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:321)
在org .hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
在org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
在org.hibernate.event .def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
在org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
在org.hibernate.event.def.DefaultSaveOrUpdateEventListe ner.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
在org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
在org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate( DefaultSaveOrUpdateEventListener.java:93)
在org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:705)
在org.hibernate.impl.SessionImpl.save(SessionImpl.java:693)
在org.hibernate.impl.SessionImpl.save(SessionImpl.java:689)
at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl。 java:25)
在java.lang.reflect.Method.invoke(Method.java:597)
在org.hibernate.context.ThreadLocalSessionContext $ TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:344)
at $ Proxy19.save(Unknown Source)
at com.example.myproject.MyEntityService.save(MyEntityService.java :59)< - 相关调用(见下面的注释)
在com.example.myproject.MyServlet.doPost(MyServlet.java:164)
... 32更多
导致:java.sql.SQLException:违反唯一约束MY_ENTITY_UK_1:列的重复值MY_COLUMN在语句[...]
在org.hsqldb.jdbc.Util.throwError(Unknown Source)
在org.hsqldb.jdbc.jdbcPreparedStatement.executeUpdate(未知来源)
在com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
在org.hibernate .id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:57)
... 54更多



在这个例子中,还有很多。我们最关心的是寻找来自我们的代码的方法,这将是 com.example.myproject 包中的任何内容。从第二个例子(上图)我们首先要看下面的根本原因,这是:

  :java.sql.SQLException 

然而,所有的方法调用都是库代码。所以我们将转到上面的Caused by,并寻找源自我们的代码的第一个方法调用,它是:

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

像以前的例子一样,我们应该看看 MyEntityService.java 59 ,因为这是这个错误发生的地方有一点很明显出了什么问题,因为SQLException指出了错误,但调试过程是我们之后的)。


Sometimes when I run my application it gives me an error that looks like:

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)

People have referred to this as a "stack trace". What is a stack trace? What can it tell me about the error that's happening in my program?


About this question - quite often I see a question come through where a novice programmer is "getting an error", and they simply paste their stack trace and some random block of code without understanding what the stack trace is or how they can use it. This question is intended as a reference for novice programmers who might need help understanding the value of a stack trace.

解决方案

In simple terms, a stack trace is a list of the method calls that the application was in the middle of when an Exception was thrown.

Simple Example

With the example given in the question, we can determine exactly where the exception was thrown in the application. Let's have a look at the 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)

This is a very simple stack trace. If we start at the beginning of the list of "at ...", we can tell where our error happened. What we're looking for is the topmost method call that is part of our application. In this case, it's:

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

To debug this, we can open up Book.java and look at line 16, which is:

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

This would indicate that something (probably title) is null in the above code.

Example with a chain of exceptions

Sometimes applications will catch an Exception and re-throw it as the cause of another Exception. This typically looks like:

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   }

This might give you a stack trace that looks like:

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

What's different about this one is the "Caused by". Sometimes exceptions will have multiple "Caused by" sections. For these, you typically want to find the "root cause", which will be one of the lowest "Caused by" sections in the stack trace. In our case, it's:

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

Again, with this exception we'd want to look at line 22 of Book.java to see what might cause the NullPointerException here.

More daunting example with library code

Usually stack traces are much more complex than the two examples above. Here's an example (it's a long one, but demonstrates several levels of chained 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

In this example, there's a lot more. What we're mostly concerned about is looking for methods that are from our code, which would be anything in the com.example.myproject package. From the second example (above), we'd first want to look down for the root cause, which is:

Caused by: java.sql.SQLException

However, all the method calls under that are library code. So we'll move up to the "Caused by" above it, and look for the first method call originating from our code, which is:

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

Like in previous examples, we should look at MyEntityService.java on line 59, because that's where this error originated (this one's a bit obvious what went wrong, since the SQLException states the error, but the debugging procedure is what we're after).

这篇关于什么是堆栈跟踪,如何使用它来调试我的应用程序错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆