Get the Current Stack Trace in Java – 在Java中获取当前的堆栈跟踪

最后修改: 2022年 8月 3日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

As a Java developer, coming across the concept of a stack trace is very common when dealing with exceptions.

作为一名Java开发人员,在处理异常时,接触到堆栈跟踪的概念是非常常见的。

In this tutorial, we’ll understand what a stack trace is and how to use it while programming/debugging. Moreover, we’ll also go through the StackTraceElement class. Finally, we’ll learn how to get it using the Thread and Throwable classes.

在本教程中,我们将了解什么是堆栈跟踪以及如何在编程/调试时使用它。此外,我们还将了解StackTraceElement类。最后,我们将学习如何使用ThreadThrowable类获得它。

2. What Is a Stack Trace?

2.什么是堆栈跟踪?

A stack trace, also called a backtrace, is a list of stack frames. In simple words, these frames represent a moment during program execution.

堆栈跟踪,也称为回溯,是一个堆栈帧的列表。简单地说,这些帧代表了程序执行过程中的一个时刻。

A stack frame contains information about a method that the code has called. It’s a list of frames that starts at the current method and extends to when the program started.

堆栈帧包含了代码所调用的方法的信息。它是一个框架的列表,从当前的方法开始,延伸到程序开始时。

To understand this better, let’s look at a quick example where we’ve dumped the current stack trace after an exception:

为了更好地理解这一点,让我们看一个快速的例子,我们在发生异常后转储了当前的堆栈跟踪。

public class DumpStackTraceDemo 
{ 
    public static void main(String[] args) {
        methodA(); 
    } 

    public static void methodA() {
        try {
            int num1 = 5/0; // java.lang.ArithmeticException: divide by zero
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

In the above example, methodA() throws ArithmeticException, which, in turn, dumps the current stack trace in the catch block:

在上面的例子中,methodA()抛出了ArithmeticException,这又在catch块中转储了当前堆栈跟踪。

java.lang.ArithmeticException: / by zero
at main.java.com.baeldung.tutorials.DumpStackTraceDemo.methodA(DumpStackTraceDemo.java:11)
at main.java.com.baeldung.tutorials.DumpStackTraceDemo.main(DumpStackTraceDemo.java:6)

3. The StackTraceElement Class

3.StackTraceElement

A stack trace consists of elements of the StackTraceElement class. We can use the following methods to get the class and method names, respectively:

堆栈跟踪由StackTraceElement类的元素组成。我们可以使用以下方法来分别获得类和方法的名称。

  • getClassName – returns the fully qualified name of the class containing the current execution point.
  • getMethodName – returns the name of the method containing the execution point represented by this stack trace element.

We can see a complete list of methods and their details in the StackTraceElement class in the Java API documentation.

我们可以在Java API文档中的StackTraceElement类中看到完整的方法列表及其细节。

4. Get a Stack Trace Using the Thread Class

4.使用Thread类获取堆栈跟踪

We can obtain a stack trace from a thread by calling the getStackTrace() method on the Thread instance. It returns an array of StackTraceElement, from which details about stack frames of the thread can be found.

我们可以通过调用Thread实例上的getStackTrace()方法来获得一个线程的堆栈跟踪。它返回一个StackTraceElement数组,从中可以找到关于线程的堆栈帧的详细信息。

Let’s see an example:

让我们看一个例子。

public class StackTraceUsingThreadDemo {

    public static void main(String[] args) {
        methodA();
    }
    
    public static StackTraceElement[] methodA() {
        return methodB();
    }

    public static StackTraceElement[] methodB() {
        Thread thread = Thread.currentThread();
        return thread.getStackTrace();
    }
}

In the above class, the method calls happen in the following manner – main() -> methodA() -> methodB() -> getStackTrace().

在上述类中,方法调用以下列方式发生 – main() -> methodA() -> methodB() -> getStackTrace().

Let’s verify it with the following test case where the test case method is calling methodA():

让我们用下面的测试案例来验证它,测试案例方法正在调用methodA()

@Test
public void whenElementIsFetchedUsingThread_thenCorrectMethodAndClassIsReturned() {
    StackTraceElement[] stackTrace = new StackTraceUsingThreadDemo().methodA();
    
    StackTraceElement elementZero = stackTrace[0];
    assertEquals("java.lang.Thread", elementZero.getClassName());
    assertEquals("getStackTrace", elementZero.getMethodName());
    
    StackTraceElement elementOne = stackTrace[1];
    assertEquals("com.baeldung.tutorials.StackTraceUsingThreadDemo", elementOne.getClassName());
    assertEquals("methodB", elementOne.getMethodName());
    
    StackTraceElement elementTwo = stackTrace[2];
    assertEquals("com.baeldung.tutorials.StackTraceUsingThreadDemo", elementTwo.getClassName());
    assertEquals("methodA", elementTwo.getMethodName());
    
    StackTraceElement elementThree = stackTrace[3];
    assertEquals("test.java.com.baeldung.tutorials.CurrentStacktraceDemoUnitTest", elementThree.getClassName());
    assertEquals("whenElementIsFetchedUsingThread_thenCorrectMethodAndClassIsReturned", elementThree.getMethodName());
}

In the above test case, we fetched an array of StackTraceElement using methodB() of StackTraceUsingThreadDemo class. Then, verified method and class names in the stack trace using getClassName() and getMethodName() methods of StackTraceElement class.

在上述测试案例中,我们使用StackTraceUsingThreadDemo类的 methodB()来获取StackTraceElement数组。然后,使用getClassName()getMethodName()类的方法验证了堆栈跟踪中的方法和类名。

5. Get a Stack Trace Using the Throwable Class

5.使用Throwable类获取堆栈跟踪

When any Java program throws a Throwable object, instead of simply printing it on the console or logging it, we can obtain an array of StackTraceElement objects by calling the getStackTrace() method.

当任何Java程序抛出一个Throwable对象时,我们可以通过调用getStackTrace()方法获得一个StackTraceElement对象的数组,而不是简单地在控制台打印或记录它。

Let’s look at an example:

我们来看看一个例子。

public class StackTraceUsingThrowableDemo {
    
    public static void main(String[] args) {
        methodA(); 
    } 

    public static StackTraceElement[] methodA() {
        try {
            methodB();
        } catch (Throwable t) {
            return t.getStackTrace();
        }
        return null;
    }

    public static void methodB() throws Throwable {
        throw new Throwable("A test exception");
    }
}

Here, the method calls happen in the following manner – main() -> methodA() -> methodB() -> getStackTrace().

在这里,方法调用以下列方式发生 – main() -> methodA() -> methodB() -> getStackTrace().

Let’s verify it using a test:

让我们用一个测试来验证它。

@Test
public void whenElementIsFecthedUsingThrowable_thenCorrectMethodAndClassIsReturned() {
    StackTraceElement[] stackTrace = new StackTraceUsingThrowableDemo().methodA();

    StackTraceElement elementZero = stackTrace[0];
    assertEquals("com.baeldung.tutorials.StackTraceUsingThrowableDemo", elementZero.getClassName());
    assertEquals("methodB", elementZero.getMethodName());

    StackTraceElement elementOne = stackTrace[1];
    assertEquals("com.baeldung.tutorials.StackTraceUsingThrowableDemo", elementOne.getClassName());
    assertEquals("methodA", elementOne.getMethodName());

    StackTraceElement elementThree = stackTrace[2];
    assertEquals("test.java.com.baeldung.tutorials.CurrentStacktraceDemoUnitTest", elementThree.getClassName());
    assertEquals("whenElementIsFecthedUsingThrowable_thenCorrectMethodAndClassIsReturned", elementThree.getMethodName());
}

In the above test case, we fetched an array of StackTraceElement using methodB() of StackTraceUsingThrowableDemo class. Then, verified method and class names to understand the order of elements in the array of StackTraceElement class.

在上述测试案例中,我们使用StackTraceUsingThrowableDemo类的 methodB()来获取StackTraceElement数组。然后,验证了方法和类的名称,以了解StackTraceElement类的数组中元素的顺序。

6. Conclusion

6.结语

In this article, we learned about the Java stack trace and how we can print it using printStackTrace() method, in case of an exception. We also looked at how to get the current stack trace using the Thread and Throwable classes.

在这篇文章中,我们了解了Java的堆栈跟踪,以及在出现异常时,我们如何使用printStackTrace()方法来打印它。我们还研究了如何使用ThreadThrowable类来获取当前的堆栈跟踪。

As always, the complete code samples for this article can be found over on GitHub.

一如既往,本文的完整代码样本可以在GitHub上找到