什么是堆栈跟踪,如何使用它来调试应用程序错误?

时间:2021-05-01 20:51:34

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.

关于这个问题,我经常看到一个问题,一个新手程序员会“得到一个错误”,他们只是简单地粘贴他们的堆栈跟踪和一些随机的代码块,而不理解堆栈跟踪是什么或者他们如何使用它。这个问题是作为新手程序员的参考,他们可能需要帮助理解堆栈跟踪的值。

7 个解决方案

#1


452  

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…”我们可以知道我们的错误发生在哪里。我们正在寻找的是我们应用程序中的topmost方法调用。在这种情况下,它是:

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:

为了调试这个,我们可以打开书本。java和第16行,也就是:

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.

再一次,有了这个例外,我们想看一下第22行。java可以看到什么原因导致了NullPointerException。

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:

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

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).

和前面的例子一样,我们应该看看MyEntityService。第59行的java,因为这是错误产生的地方(这一点很明显是错误的,因为SQLException是错误的,但是调试过程是我们以后要做的)。

#2


62  

I am posting this answer so the topmost answer (when sorted by activity) is not one that is just plain wrong.

我发布了这个答案,所以最上面的答案(按活动排序)不是一个完全错误的答案。

What is a Stacktrace?

什么是加亮?

A stacktrace is a very helpful debugging tool. It shows the call stack (meaning, the stack of functions that were called up to that point) at the time an uncaught exception was thrown (or the time the stacktrace was generated manually). This is very useful because it doesn't only show you where the error happened, but also how the program ended up in that place of the code. This leads over to the next question:

stacktrace是一个非常有用的调试工具。它显示了调用堆栈(也就是被调用到那个点的函数堆栈),这时抛出一个未捕获的异常(或者手动生成堆栈跟踪的时间)。这非常有用,因为它不仅显示了错误发生的地方,而且还显示了程序是如何在代码的那个位置结束的。这就引出了下一个问题:

What is an Exception?

一个例外是什么?

An Exception is what the runtime environment uses to tell you that an error occurred. Popular examples are NullPointerException, IndexOutOfBoundsException or ArithmeticException. Each of these are caused when you try to do something that is not possible. For example, a NullPointerException will be thrown when you try to dereference a Null-object:

一个异常是运行时环境用来告诉您发生错误的地方。流行的例子是NullPointerException、IndexOutOfBoundsException或算术异常。当你试图做一些不可能的事情时,每一个都是由你造成的。例如,当您试图取消一个空对象时,将抛出NullPointerException:

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.

How should I deal with Stacktraces/Exceptions?

我应该如何处理堆栈跟踪/异常?

At first, find out what is causing the Exception. Try googleing the name of the exception to find out, what is the cause of that exception. Most of the time it will be caused by incorrect code. In the given examples above, all of the exceptions are caused by incorrect code. So for the NullPointerException example you could make sure that a is never null at that time. You could, for example, initialise a or include a check like this one:

首先,找出导致异常的原因。试试google一下这个异常的名字,找出它的原因。大多数时候它将由不正确的代码引起。在上面的例子中,所有的异常都是由不正确的代码引起的。对于NullPointerException的例子,你可以确保a在那个时候从不为空。例如,您可以初始化a或包括如下的检查:

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

This way, the offending line is not executed if a==null. Same goes for the other examples.

这样,如果a==null,就不会执行出错的行。其他的例子也一样。

Sometimes you can't make sure that you don't get an exception. For example, if you are using a network connection in your program, you cannot stop the computer from loosing it's internet connection (e.g. you can't stop the user from disconnecting the computer's network connection). In this case the network library will probably throw an exception. Now you should catch the exception and handle it. This means, in the example with the network connection, you should try to reopen the connection or notify the user or something like that. Also, whenever you use catch, always catch only the exception you want to catch, do not use broad catch statements like catch (Exception e) that would catch all exceptions. This is very important, because otherwise you might accidentally catch the wrong exception and react in the wrong way.

有时你不能确保你没有得到一个例外。例如,如果你在你的程序中使用网络连接,你不能阻止计算机失去它的网络连接(例如,你不能阻止用户断开连接计算机的网络连接)。在这种情况下,网络库可能会抛出一个异常。现在您应该捕获异常并处理它。这意味着,在网络连接的示例中,您应该尝试重新打开连接,或者通知用户或类似的东西。而且,每当您使用catch时,总是只捕获您想要捕获的异常,不要使用catch(异常e)这样的宽捕获语句,捕获所有异常。这是非常重要的,否则您可能会意外捕获错误的异常并以错误的方式作出反应。

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!")
}

Why should I not use catch (Exception e)?

为什么我不使用catch(例外e)?

Let's use a small example to show why you should not just catch all 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;
    }
}

What this code is trying to do is to catch the ArithmeticException caused by a possible division by 0. But it also catches a possible NullPointerException that is thrown if a or b are null. This means, you might get a NullPointerException but you'll treat it as an ArithmeticException and probably do the wrong thing. In the best case you still miss that there was a NullPointerException. Stuff like that makes debugging much harder, so don't do that.

这段代码试图做的是捕获由可能的除0引起的算术异常。但是,如果a或b为空,它也会捕获一个可能的NullPointerException。这意味着,您可能会得到一个NullPointerException,但是您将把它视为一个算术异常,并且可能做了错误的事情。在最好的情况下,您仍然忽略了一个NullPointerException。像这样的东西使调试更加困难,所以不要这样做。

TLDR

TLDR

  1. Figure out what is the cause of the exception and fix it, so that it doesn't throw the exception at all.
  2. 找出异常的原因并修复它,这样它就不会抛出异常。
  3. If 1. is not possible, catch the specific exception and handle it.

    如果1。不可能,捕获特定的异常并处理它。

    • Never just add a try/catch and then just ignore the exception! Don't do that!
    • 不要只是添加一个try/catch,然后忽略这个异常!别干那事!
    • Never use catch (Exception e), always catch specific Exceptions. That will save you a lot of headaches.
    • 不要使用catch(异常e),总是捕获特定的异常。这样可以省去很多麻烦。

#3


17  

To add on to what Rob has mentioned. Setting break points in your application allows for the step-by-step processing of the stack. This enables the developer to use the debugger to see at what exact point the method is doing something that was unanticipated.

再加上Rob提到的内容。在应用程序中设置断点可以逐步处理堆栈。这使得开发人员可以使用调试器来查看该方法所做的事情是没有预料到的。

Since Rob has used the NullPointerException (NPE) to illustrate something common, we can help to remove this issue in the following manner:

由于Rob使用NullPointerException (NPE)来说明一些常见的事情,我们可以通过以下方式帮助解决这个问题:

if we have a method that takes parameters such as: void (String firstName)

如果我们有一个方法,它接受诸如:void(字符串firstName)这样的参数

In our code we would want to evaluate that firstName contains a value, we would do this like so: if(firstName == null || firstName.equals("")) return;

在我们的代码中,我们想要计算firstName包含一个值,我们可以这样做:if(firstName == null || firstName.equals(“)”)返回;

The above prevents us from using firstName as an unsafe parameter. Therefore by doing null checks before processing we can help to ensure that our code will run properly. To expand on an example that utilizes an object with methods we can look here:

上面的内容阻止我们使用firstName作为不安全参数。因此,在处理之前进行空检查可以帮助确保代码正常运行。为了扩展一个利用对象的例子,我们可以看这里:

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

如果(dog == null || dog)。firstName = = null)返回;

The above is the proper order to check for nulls, we start with the base object, dog in this case, and then begin walking down the tree of possibilities to make sure everything is valid before processing. If the order were reversed a NPE could potentially be thrown and our program would crash.

以上是检查nulls的正确顺序,我们从基本对象开始,在这种情况下,然后开始沿着可能的树向下走,以确保在处理之前一切都是有效的。如果订单被取消,NPE可能会被抛出,我们的程序会崩溃。

#4


14  

There is one more stacktrace feature offered by Throwable family - the possibility to manipulate stack trace information.

还有一个由可转换的家族提供的堆栈跟踪功能——可以操纵堆栈跟踪信息。

Standard behavior:

标准的行为:

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();
    }
}

Stack trace:

堆栈跟踪:

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)

Manipulated stack trace:

操纵堆栈跟踪:

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();
    }
}

Stack trace:

堆栈跟踪:

Exception in thread "main" java.lang.RuntimeException
    at OtherClass.methodX(String.java:99)
    at OtherClass.methodY(String.java:55)

#5


10  

To understand the name: A stack trace is a a list of Exceptions( or you can say a list of "Cause by"), from the most surface Exception(e.g. Service Layer Exception) to the deepest one (e.g. Database Exception). Just like the reason we call it 'stack' is because stack is First in Last out (FILO), the deepest exception was happened in the very beginning, then a chain of exception was generated a series of consequences, the surface Exception was the last one happened in time, but we see it in the first place.

要理解这个名称:堆栈跟踪是一个异常列表(或者您可以说一个“原因”列表),从最表面的异常(例如:服务层异常)到最深的一个(例如,数据库异常)。就像我们称之为“堆栈”的原因是堆栈是第一个在去年(费罗),最深的例外是发生在一开始,然后一连串的例外是产生一系列后果,表面异常发生的是最后一个,但是我们首先看到它。

Key 1:A tricky and important thing here need to be understand is : the deepest cause may not be the "root cause", because if you write some "bad code", it may cause some exception underneath which is deeper than its layer. For example, a bad sql query may cause SQLServerException connection reset in the bottem instead of syndax error, which may just in the middle of the stack.

关键1:需要理解的一个棘手而重要的事情是:最深层的原因可能不是“根本原因”,因为如果你写了一些“糟糕的代码”,它可能会导致下面的一些异常,比它的层更深。例如,一个糟糕的sql查询可能会导致在bottem中重新设置SQLServerException,而不是syndax错误,而syndax可能正好位于堆栈的中间。

-> Locate the root cause in the middle is your job. 什么是堆栈跟踪,如何使用它来调试应用程序错误?

->找到中间的原因是你的工作。

Key 2:Another tricky but important thing is inside each "Cause by" block, the first line was the deepest layer and happen first place for this block. For instance,

关键2:另一个棘手但重要的事情是在每一个“因”块中,第一行是最深层的,并且是这个块的第一个位置。例如,

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 was called by Auther.java:25 which was called by Bootstrap.java:14, Book.java:16 was the root cause. Here attach a diagram sort the trace stack in chronological order. 什么是堆栈跟踪,如何使用它来调试应用程序错误?

书。java:16被Auther调用。java:由Bootstrap调用的25。java:14日书。java:16是根本原因。这里附加一个图表按时间顺序对跟踪堆栈进行排序。

#6


8  

Just to add to the other examples, there are inner(nested) classes that appear with the $ sign. For example:

为了添加到其他示例中,有一些内部的(嵌套的)类以$符号出现。例如:

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();
    }
}

Will result in this stack trace:

将导致此堆栈跟踪:

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)

#7


5  

The other posts describe what a stack trace is, but it can still be hard to work with.

其他的帖子描述了堆栈跟踪是什么,但是仍然很难处理。

If you get a stack trace and want to trace the cause of the exception, a good start point in understanding it is to use the Java Stack Trace Console in Eclipse. If you use another IDE there may be a similar feature, but this answer is about Eclipse.

如果您获得了一个堆栈跟踪,并希望跟踪异常的原因,那么理解它的一个好起点是在Eclipse中使用Java堆栈跟踪控制台。如果您使用另一个IDE,可能会有类似的特性,但是这个答案是关于Eclipse的。

First, ensure that you have all of your Java sources accessible in an Eclipse project.

首先,确保您的所有Java源代码都可以在Eclipse项目中访问。

Then in the Java perspective, click on the Console tab (usually at the bottom). If the Console view is not visible, go to the menu option Window -> Show View and select Console.

然后在Java透视图中,单击Console选项卡(通常在底部)。如果控制台视图不可见,转到菜单选项窗口->显示视图并选择控制台。

Then in the console window, click on the following button (on the right)

然后在控制台窗口中,点击下面的按钮(在右边)

什么是堆栈跟踪,如何使用它来调试应用程序错误?

and then select Java Stack Trace Console from the drop-down list.

然后从下拉列表中选择Java堆栈跟踪控制台。

Paste your stack trace into the console. It will then provide a list of links into your source code and any other source code available.

将堆栈跟踪粘贴到控制台。然后它将提供一个链接列表到您的源代码和其他可用的源代码中。

This is what you might see (image from the Eclipse documentation):

这是您可能看到的(来自Eclipse文档的图像):

什么是堆栈跟踪,如何使用它来调试应用程序错误?

The most recent method call made will be the top of the stack, which is the top line (excluding the message text). Going down the stack goes back in time. The second line is the method that calls the first line, etc.

最近的方法调用将是堆栈的顶部,这是顶行(不包括消息文本)。从堆栈上往下走可以回溯到时间。第二行是调用第一行的方法,等等。

If you are using open-source software, you might need to download and attach to your project the sources if you want to examine. Download the source jars, in your project, open the Referenced Libraries folder to find your jar for your open-source module (the one with the class files) then right click, select Properties and attach the source jar.

如果您使用的是开源软件,您可能需要下载并附加到您的项目中,如果您想要检查的话。在您的项目中下载源jar,打开引用的库文件夹,找到您的开源模块(带有类文件的jar)的jar,然后右键单击,选择Properties并附加源jar。

#1


452  

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…”我们可以知道我们的错误发生在哪里。我们正在寻找的是我们应用程序中的topmost方法调用。在这种情况下,它是:

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:

为了调试这个,我们可以打开书本。java和第16行,也就是:

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.

再一次,有了这个例外,我们想看一下第22行。java可以看到什么原因导致了NullPointerException。

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:

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

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).

和前面的例子一样,我们应该看看MyEntityService。第59行的java,因为这是错误产生的地方(这一点很明显是错误的,因为SQLException是错误的,但是调试过程是我们以后要做的)。

#2


62  

I am posting this answer so the topmost answer (when sorted by activity) is not one that is just plain wrong.

我发布了这个答案,所以最上面的答案(按活动排序)不是一个完全错误的答案。

What is a Stacktrace?

什么是加亮?

A stacktrace is a very helpful debugging tool. It shows the call stack (meaning, the stack of functions that were called up to that point) at the time an uncaught exception was thrown (or the time the stacktrace was generated manually). This is very useful because it doesn't only show you where the error happened, but also how the program ended up in that place of the code. This leads over to the next question:

stacktrace是一个非常有用的调试工具。它显示了调用堆栈(也就是被调用到那个点的函数堆栈),这时抛出一个未捕获的异常(或者手动生成堆栈跟踪的时间)。这非常有用,因为它不仅显示了错误发生的地方,而且还显示了程序是如何在代码的那个位置结束的。这就引出了下一个问题:

What is an Exception?

一个例外是什么?

An Exception is what the runtime environment uses to tell you that an error occurred. Popular examples are NullPointerException, IndexOutOfBoundsException or ArithmeticException. Each of these are caused when you try to do something that is not possible. For example, a NullPointerException will be thrown when you try to dereference a Null-object:

一个异常是运行时环境用来告诉您发生错误的地方。流行的例子是NullPointerException、IndexOutOfBoundsException或算术异常。当你试图做一些不可能的事情时,每一个都是由你造成的。例如,当您试图取消一个空对象时,将抛出NullPointerException:

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.

How should I deal with Stacktraces/Exceptions?

我应该如何处理堆栈跟踪/异常?

At first, find out what is causing the Exception. Try googleing the name of the exception to find out, what is the cause of that exception. Most of the time it will be caused by incorrect code. In the given examples above, all of the exceptions are caused by incorrect code. So for the NullPointerException example you could make sure that a is never null at that time. You could, for example, initialise a or include a check like this one:

首先,找出导致异常的原因。试试google一下这个异常的名字,找出它的原因。大多数时候它将由不正确的代码引起。在上面的例子中,所有的异常都是由不正确的代码引起的。对于NullPointerException的例子,你可以确保a在那个时候从不为空。例如,您可以初始化a或包括如下的检查:

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

This way, the offending line is not executed if a==null. Same goes for the other examples.

这样,如果a==null,就不会执行出错的行。其他的例子也一样。

Sometimes you can't make sure that you don't get an exception. For example, if you are using a network connection in your program, you cannot stop the computer from loosing it's internet connection (e.g. you can't stop the user from disconnecting the computer's network connection). In this case the network library will probably throw an exception. Now you should catch the exception and handle it. This means, in the example with the network connection, you should try to reopen the connection or notify the user or something like that. Also, whenever you use catch, always catch only the exception you want to catch, do not use broad catch statements like catch (Exception e) that would catch all exceptions. This is very important, because otherwise you might accidentally catch the wrong exception and react in the wrong way.

有时你不能确保你没有得到一个例外。例如,如果你在你的程序中使用网络连接,你不能阻止计算机失去它的网络连接(例如,你不能阻止用户断开连接计算机的网络连接)。在这种情况下,网络库可能会抛出一个异常。现在您应该捕获异常并处理它。这意味着,在网络连接的示例中,您应该尝试重新打开连接,或者通知用户或类似的东西。而且,每当您使用catch时,总是只捕获您想要捕获的异常,不要使用catch(异常e)这样的宽捕获语句,捕获所有异常。这是非常重要的,否则您可能会意外捕获错误的异常并以错误的方式作出反应。

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!")
}

Why should I not use catch (Exception e)?

为什么我不使用catch(例外e)?

Let's use a small example to show why you should not just catch all 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;
    }
}

What this code is trying to do is to catch the ArithmeticException caused by a possible division by 0. But it also catches a possible NullPointerException that is thrown if a or b are null. This means, you might get a NullPointerException but you'll treat it as an ArithmeticException and probably do the wrong thing. In the best case you still miss that there was a NullPointerException. Stuff like that makes debugging much harder, so don't do that.

这段代码试图做的是捕获由可能的除0引起的算术异常。但是,如果a或b为空,它也会捕获一个可能的NullPointerException。这意味着,您可能会得到一个NullPointerException,但是您将把它视为一个算术异常,并且可能做了错误的事情。在最好的情况下,您仍然忽略了一个NullPointerException。像这样的东西使调试更加困难,所以不要这样做。

TLDR

TLDR

  1. Figure out what is the cause of the exception and fix it, so that it doesn't throw the exception at all.
  2. 找出异常的原因并修复它,这样它就不会抛出异常。
  3. If 1. is not possible, catch the specific exception and handle it.

    如果1。不可能,捕获特定的异常并处理它。

    • Never just add a try/catch and then just ignore the exception! Don't do that!
    • 不要只是添加一个try/catch,然后忽略这个异常!别干那事!
    • Never use catch (Exception e), always catch specific Exceptions. That will save you a lot of headaches.
    • 不要使用catch(异常e),总是捕获特定的异常。这样可以省去很多麻烦。

#3


17  

To add on to what Rob has mentioned. Setting break points in your application allows for the step-by-step processing of the stack. This enables the developer to use the debugger to see at what exact point the method is doing something that was unanticipated.

再加上Rob提到的内容。在应用程序中设置断点可以逐步处理堆栈。这使得开发人员可以使用调试器来查看该方法所做的事情是没有预料到的。

Since Rob has used the NullPointerException (NPE) to illustrate something common, we can help to remove this issue in the following manner:

由于Rob使用NullPointerException (NPE)来说明一些常见的事情,我们可以通过以下方式帮助解决这个问题:

if we have a method that takes parameters such as: void (String firstName)

如果我们有一个方法,它接受诸如:void(字符串firstName)这样的参数

In our code we would want to evaluate that firstName contains a value, we would do this like so: if(firstName == null || firstName.equals("")) return;

在我们的代码中,我们想要计算firstName包含一个值,我们可以这样做:if(firstName == null || firstName.equals(“)”)返回;

The above prevents us from using firstName as an unsafe parameter. Therefore by doing null checks before processing we can help to ensure that our code will run properly. To expand on an example that utilizes an object with methods we can look here:

上面的内容阻止我们使用firstName作为不安全参数。因此,在处理之前进行空检查可以帮助确保代码正常运行。为了扩展一个利用对象的例子,我们可以看这里:

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

如果(dog == null || dog)。firstName = = null)返回;

The above is the proper order to check for nulls, we start with the base object, dog in this case, and then begin walking down the tree of possibilities to make sure everything is valid before processing. If the order were reversed a NPE could potentially be thrown and our program would crash.

以上是检查nulls的正确顺序,我们从基本对象开始,在这种情况下,然后开始沿着可能的树向下走,以确保在处理之前一切都是有效的。如果订单被取消,NPE可能会被抛出,我们的程序会崩溃。

#4


14  

There is one more stacktrace feature offered by Throwable family - the possibility to manipulate stack trace information.

还有一个由可转换的家族提供的堆栈跟踪功能——可以操纵堆栈跟踪信息。

Standard behavior:

标准的行为:

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();
    }
}

Stack trace:

堆栈跟踪:

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)

Manipulated stack trace:

操纵堆栈跟踪:

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();
    }
}

Stack trace:

堆栈跟踪:

Exception in thread "main" java.lang.RuntimeException
    at OtherClass.methodX(String.java:99)
    at OtherClass.methodY(String.java:55)

#5


10  

To understand the name: A stack trace is a a list of Exceptions( or you can say a list of "Cause by"), from the most surface Exception(e.g. Service Layer Exception) to the deepest one (e.g. Database Exception). Just like the reason we call it 'stack' is because stack is First in Last out (FILO), the deepest exception was happened in the very beginning, then a chain of exception was generated a series of consequences, the surface Exception was the last one happened in time, but we see it in the first place.

要理解这个名称:堆栈跟踪是一个异常列表(或者您可以说一个“原因”列表),从最表面的异常(例如:服务层异常)到最深的一个(例如,数据库异常)。就像我们称之为“堆栈”的原因是堆栈是第一个在去年(费罗),最深的例外是发生在一开始,然后一连串的例外是产生一系列后果,表面异常发生的是最后一个,但是我们首先看到它。

Key 1:A tricky and important thing here need to be understand is : the deepest cause may not be the "root cause", because if you write some "bad code", it may cause some exception underneath which is deeper than its layer. For example, a bad sql query may cause SQLServerException connection reset in the bottem instead of syndax error, which may just in the middle of the stack.

关键1:需要理解的一个棘手而重要的事情是:最深层的原因可能不是“根本原因”,因为如果你写了一些“糟糕的代码”,它可能会导致下面的一些异常,比它的层更深。例如,一个糟糕的sql查询可能会导致在bottem中重新设置SQLServerException,而不是syndax错误,而syndax可能正好位于堆栈的中间。

-> Locate the root cause in the middle is your job. 什么是堆栈跟踪,如何使用它来调试应用程序错误?

->找到中间的原因是你的工作。

Key 2:Another tricky but important thing is inside each "Cause by" block, the first line was the deepest layer and happen first place for this block. For instance,

关键2:另一个棘手但重要的事情是在每一个“因”块中,第一行是最深层的,并且是这个块的第一个位置。例如,

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 was called by Auther.java:25 which was called by Bootstrap.java:14, Book.java:16 was the root cause. Here attach a diagram sort the trace stack in chronological order. 什么是堆栈跟踪,如何使用它来调试应用程序错误?

书。java:16被Auther调用。java:由Bootstrap调用的25。java:14日书。java:16是根本原因。这里附加一个图表按时间顺序对跟踪堆栈进行排序。

#6


8  

Just to add to the other examples, there are inner(nested) classes that appear with the $ sign. For example:

为了添加到其他示例中,有一些内部的(嵌套的)类以$符号出现。例如:

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();
    }
}

Will result in this stack trace:

将导致此堆栈跟踪:

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)

#7


5  

The other posts describe what a stack trace is, but it can still be hard to work with.

其他的帖子描述了堆栈跟踪是什么,但是仍然很难处理。

If you get a stack trace and want to trace the cause of the exception, a good start point in understanding it is to use the Java Stack Trace Console in Eclipse. If you use another IDE there may be a similar feature, but this answer is about Eclipse.

如果您获得了一个堆栈跟踪,并希望跟踪异常的原因,那么理解它的一个好起点是在Eclipse中使用Java堆栈跟踪控制台。如果您使用另一个IDE,可能会有类似的特性,但是这个答案是关于Eclipse的。

First, ensure that you have all of your Java sources accessible in an Eclipse project.

首先,确保您的所有Java源代码都可以在Eclipse项目中访问。

Then in the Java perspective, click on the Console tab (usually at the bottom). If the Console view is not visible, go to the menu option Window -> Show View and select Console.

然后在Java透视图中,单击Console选项卡(通常在底部)。如果控制台视图不可见,转到菜单选项窗口->显示视图并选择控制台。

Then in the console window, click on the following button (on the right)

然后在控制台窗口中,点击下面的按钮(在右边)

什么是堆栈跟踪,如何使用它来调试应用程序错误?

and then select Java Stack Trace Console from the drop-down list.

然后从下拉列表中选择Java堆栈跟踪控制台。

Paste your stack trace into the console. It will then provide a list of links into your source code and any other source code available.

将堆栈跟踪粘贴到控制台。然后它将提供一个链接列表到您的源代码和其他可用的源代码中。

This is what you might see (image from the Eclipse documentation):

这是您可能看到的(来自Eclipse文档的图像):

什么是堆栈跟踪,如何使用它来调试应用程序错误?

The most recent method call made will be the top of the stack, which is the top line (excluding the message text). Going down the stack goes back in time. The second line is the method that calls the first line, etc.

最近的方法调用将是堆栈的顶部,这是顶行(不包括消息文本)。从堆栈上往下走可以回溯到时间。第二行是调用第一行的方法,等等。

If you are using open-source software, you might need to download and attach to your project the sources if you want to examine. Download the source jars, in your project, open the Referenced Libraries folder to find your jar for your open-source module (the one with the class files) then right click, select Properties and attach the source jar.

如果您使用的是开源软件,您可能需要下载并附加到您的项目中,如果您想要检查的话。在您的项目中下载源jar,打开引用的库文件夹,找到您的开源模块(带有类文件的jar)的jar,然后右键单击,选择Properties并附加源jar。