Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

November Discount Launch 2022 – Top
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:

>> GET ACCESS NOW

Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

November Discount Launch 2022 – TEMP TOP (NPI)
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:

>> GET ACCESS NOW

1. Overview

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

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.

2. What Is a Stack Trace?

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:

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

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

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

4. Get a Stack Trace Using the Thread Class

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.

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

Let's verify it with the following test case where the test case method is calling 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.

5. Get a Stack Trace Using the Throwable Class

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.

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

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.

6. Conclusion

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.

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

November Discount Launch 2022 – Bottom
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:

>> GET ACCESS NOW

Generic footer banner
Comments are closed on this article!