1. Getting a stack trace
The Java programming language offers many ways for a programmer to get information about what is happening in a program. And not just words.
For example, after C++ programs are compiled, they become one large file full of machine code, and all that is available to a programmer at runtime is the address of the block of memory that contains the machine code currently being executed. Not a lot, let's say.
But for Java, even after a program is compiled, classes remain classes, methods and variables don't disappear, and the programmer has many ways to get information about what is happening in the program.
Stack trace
For example, at point in a program's execution, you can find out the class and name of the method currently being executed. And not just one method — you can get information about the entire chain of method calls from the current method back to the main()
method.
A list that consists of the current method, and the method that invoked it, and method that called that one, etc. is called a stack trace. You can get it with this statement:
StackTraceElement[] methods = Thread.currentThread().getStackTrace();
You can also write it as two lines:
Thread current = Thread.currentThread();
StackTraceElement[] methods = current.getStackTrace();
The static currentThread()
method of the Thread
class returns a reference to a Thread
object, which contains information about the current thread, i.e. the current thread of execution. You will learn more about threads in Levels 17 and 18 of the Java Core quest.
This Thread
object has a getStackTrace()
method, which returns an array of StackTraceElement
objects, each of which contains information about a method. Taken together, all these elements form a stack trace.
Example:
Code |
---|
|
Console output |
|
As we can see in the example's console output, the getStackTrace()
method returned an array of three elements:
getStackTrace()
method of theThread
classtest()
method of theMain
classmain()
method of theMain
class
From this stack trace, we can conclude that:
- The
Thread.getStackTrace()
method was called by theMain.test()
method on line 11 of the Main.java file - The
Main.test()
method was called by theMain.main()
method on line 5 of the Main.java file - Nobody called the
Main.main()
method — this is the first method in the chain of calls.
By the way, only some of the available information was displayed on the screen. Everything else can be obtained directly from the StackTraceElement
object
2. StackTraceElement
As its name suggests, the StackTraceElement
class was created to store information about a stack trace element, i.e. one method in the stack trace
.
This class has the following instance methods:
Method | Description |
---|---|
|
Returns the name of the class |
|
Returns the name of the method |
|
Returns the name of the file (one file can contain multiple classes) |
|
Returns the line number in the file where the method was called |
|
Returns the name of the module (this can be null ) |
|
Returns the version of the module (this can be null ) |
They can help you get more complete information about the current call stack:
Code | Console output | Note |
---|---|---|
|
|
class name method name file name line number module name module version class name method name file name line number module name module version class name method name file name line number module name module version |
3. Stack
You already know what a stack trace is, but what is a stack (Stack class)?
A stack is a data structure to which you can add elements and from which you can retrieve elements. In doing so, you can only take elements from the end: you first take the last one added, then the second to last one added, etc.
The name stack itself suggests this behavior, like how you would interact with a stack of papers. If you put sheets 1, 2 and 3 in a stack, you have to retrieve them in reverse order: first the third sheet, then the second, and only then the first.
Java even has a special Stack collection class with the same name and behavior. This class shares a lot of behaviors with ArrayList
and LinkedList
. But it also has methods that implement stack behavior:
Methods | Description |
---|---|
|
Adds the obj element to the top of the stack |
|
Takes the element from the top of the stack (the stack depth decreases) |
|
Returns the item at the top of the stack (the stack does not change) |
|
Checks whether the collection is empty |
|
Searches for an object in the collection and returns its index |
Example:
Code | Stack contents (the top of the stack is on the right) |
---|---|
|
|
Stacks are used quite often in programming. So this is a useful collection.
4. Displaying a stack trace during exception handling
Why is a list of method calls called a stack trace? Because if you think of the list of methods as a stack of sheets of paper with method names, then when you call the next method, you add a sheet with that method's name to the stack. And the next sheet of paper goes on top of that, and so on.
When a method ends, the sheet at the top of the stack is removed. You cannot remove a sheet from the middle of the stack without removing all the sheets above it. Similarly, you cannot terminate a method in the middle of a chain of calls without terminating all the methods that it has called.
Exceptions
Another interesting use for stacks is during exception handling.
When an error occurs in a program and an exception is thrown, the exception contains the current stack trace — an array consisting of a list of methods starting, from the main method and ending with the method where the error occurred. There's even the line where the exception was thrown!
This stack trace is stored inside the exception and can be easily retrieved from it using the following method: StackTraceElement[] getStackTrace()
Example:
Code | Note |
---|---|
|
Catch the exception Get the stack trace that existed when the error occurred. |
This is a method of the Throwable
class, so all its descendants (i.e. all exceptions) have the getStackTrace()
method. Super convenient, huh?
Display the exception's stack trace
By the way, the Throwable
class has another method for working with stack traces, a method that displays all the stack trace information stored inside the exception. It is called printStackTrace()
.
Quite conveniently, you can call it on any exception.
Example:
Code |
---|
|
Console output |
|
GO TO FULL VERSION