Java 什么是堆栈跟踪,如何使用它调试应用程序错误?
有时,当我运行应用程序时,会出现如下错误:Java 什么是堆栈跟踪,如何使用它调试应用程序错误?,java,debugging,stack-trace,Java,Debugging,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.Bootst
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)
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 }
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
人们称之为“堆栈跟踪”什么是堆栈跟踪?它能告诉我程序中发生的错误是什么
关于这个问题——我经常看到一个问题,一个新手程序员“遇到了错误”,他们只是简单地粘贴他们的堆栈跟踪和一些随机代码块,而不了解堆栈跟踪是什么或如何使用它。这个问题旨在为新手程序员提供参考,这些程序员可能需要帮助理解堆栈跟踪的值。 < P>简单地说,<强>堆栈跟踪< /St>是应用程序处于异常抛出的方法调用的列表。 简单示例 通过问题中给出的示例,我们可以准确地确定在应用程序中引发异常的位置。让我们看看堆栈跟踪:
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)
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)
Exception in thread "main" java.lang.RuntimeException
at OtherClass.methodX(String.java:99)
at OtherClass.methodY(String.java:55)
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)
这是一个非常简单的堆栈跟踪。如果我们从“at…”列表的开头开始,我们就可以知道错误发生的地方。我们需要的是应用程序中最顶层的方法调用。在这种情况下,它是:
at com.example.myproject.Book.getTitle(Book.java:16)
Caused by: java.lang.NullPointerException <-- root cause
at com.example.myproject.Book.getId(Book.java:22) <-- important line
要对此进行调试,我们可以打开Book.java
并查看第16行,即:
15 public String getTitle() {
16 System.out.println(title.toString());
17 return title;
18 }
Caused by: java.sql.SQLException
at com.example.myproject.MyEntityService.save(MyEntityService.java:59)
这将表明在上述代码中有东西(可能是title
)是null
一系列例外情况的示例
有时,应用程序会捕获一个异常并将其作为另一个异常的原因重新抛出。这通常看起来像:
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)
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 }
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
这可能会为您提供如下堆栈跟踪:
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)
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 }
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
这一个的不同之处在于“引起”。有时,异常会有多个“原因”部分。对于这些,您通常希望找到“根本原因”,这将是堆栈跟踪中最低的“原因”部分之一。就我们而言,它是:
at com.example.myproject.Book.getTitle(Book.java:16)
Caused by: java.lang.NullPointerException <-- root cause
at com.example.myproject.Book.getId(Book.java:22) <-- important line
在这个例子中,还有很多。我们最关心的是从我们的代码中寻找方法,这可能是com.example.myproject
包中的任何内容。从上面的第二个示例中,我们首先要查找根本原因,即:
15 public String getTitle() {
16 System.out.println(title.toString());
17 return title;
18 }
Caused by: java.sql.SQLException
at com.example.myproject.MyEntityService.save(MyEntityService.java:59)
但是,该下的所有方法调用都是库代码。因此,我们将向上移动到上面的“起因”,并查找源自代码的第一个方法调用,即:
15 public String getTitle() {
16 System.out.println(title.toString());
17 return title;
18 }
Caused by: java.sql.SQLException
at com.example.myproject.MyEntityService.save(MyEntityService.java:59)
与前面的示例一样,我们应该查看联机59
上的MyEntityService.java
,因为这就是这个错误产生的原因(这个错误有点明显,因为SQLException声明了错误,但调试过程是我们要做的)。来补充Rob提到的内容。在应用程序中设置断点可以逐步处理堆栈。这使开发人员能够使用调试器来查看该方法在什么确切的点上正在做一些出乎意料的事情
由于Rob使用了NullPointerException
(NPE)来说明一些常见的问题,因此我们可以通过以下方式帮助消除此问题:
如果我们有一个采用如下参数的方法:void(stringfirstname)
在我们的代码中,我们希望计算firstName
是否包含一个值,我们将这样做:if(firstName==null | | firstName.equals(“”)return代码>
以上内容防止我们将firstName
用作不安全参数。因此,通过在处理之前进行空检查,我们可以帮助确保代码正常运行。要扩展使用对象和方法的示例,我们可以查看以下内容:
if(dog==null | | dog.firstName==null)返回代码>
以上是检查空值的正确顺序,我们从基本对象开始,在本例中是dog,然后开始沿着可能性树向下走,以确保在处理之前所有内容都有效。如果顺序颠倒,NPE可能会被抛出,我们的程序将崩溃。Throwable系列还提供了一个stacktrace功能,即操纵堆栈跟踪信息的可能性
标准行为:
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();
}
}
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();
}
}
堆栈跟踪:
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)
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)
Exception in thread "main" java.lang.RuntimeException
at OtherClass.methodX(String.java:99)
at OtherClass.methodY(String.java:55)
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)
操纵堆栈跟踪:
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();
}
}
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();
}
}
堆栈跟踪:
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)
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)
Exception in thread "main" java.lang.RuntimeException
at OtherClass.methodX(String.java:99)
at OtherClass.methodY(String.java:55)
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)
其他帖子描述了堆栈跟踪是什么,但它仍然很难使用
如果您得到一个堆栈跟踪,并希望跟踪异常的原因,那么了解它的一个很好的起点是使用Eclipse中的Java堆栈跟踪控制台。如果您使用另一个IDE,可能会有类似的特性,但这个答案是关于Eclipse的
首先,确保在Eclipse项目中可以访问所有Java源代码
然后在Java透视图中,单击Console选项卡(通常在底部)。如果控制台视图不可见,请转到菜单选项窗口->显示视图并选择控制台
然后在控制台窗口中,单击以下按钮(右侧)
然后从下拉列表中选择Java堆栈跟踪控制台
将堆栈跟踪粘贴到控制台中。然后,它将提供一个链接列表,链接到您的源代码和任何其他可用的源代码中
这是您可能看到的(Eclipse文档中的图像):
最近进行的方法调用将位于堆栈的顶部,即顶部行(不包括消息文本)。下一层的时间可以追溯到过去。第二行是调用第一行的方法,等等
如果您使用的是开放源代码软件,如果您想检查,可能需要下载源代码并将其附加到项目中。下载源jar,在您的项目中,打开Referenced Libraries文件夹,找到您的开源模块(即