When programming in java, there are times when you want to know where a method was called. In such a case, you can get the stack trace information and get the caller information.
Use Throwable # getStackTrace ()
to get the stack trace information.
StackTraceElement[] ste = new Throwable().getStackTrace();
for (int i = 0; i < ste.length; i++) {
System.out.println(ste[i].getClassName()); //Get class name
System.out.println(ste[i].getMethodName()); //Get method name
System.out.println(ste[i].getFileName()); //Get the file name
System.out.println(ste[i].getLineNumber()); //Get line number (cannot get in case of native method)
System.out.println(ste[i].isNativeMethod()); //Determine if it is a native method.
System.out.println(ste[i]); //Format and display stack trace information
}
You can also use Thread # getStackTrace ()
instead of Throwable # getStackTrace ()
.
StackTraceElement[] ste = Thread.currentThread().getStackTrace();
However, there are some differences in the stack trace information obtained by the two methods. Let's run the sample program and check it.
Main1
package sample;
public class Main1 {
public static void main(String[] args) {
SampleClass1 sc = new SampleClass1();
sc.method1();
}
}
class SampleClass1 {
public void method1() {
method2();
}
public void method2() {
System.out.println("Throwable#getStackTrace()Get stack trace information using");
StackTraceElement[] ste = new Throwable().getStackTrace();
for (int i = 0; i < ste.length; i++) {
System.out.println(ste[i]);
}
System.out.println("\nThread#getStackTrace()Get stack trace information using");
ste = Thread.currentThread().getStackTrace();
for (int i = 0; i < ste.length; i++) {
System.out.println(ste[i]);
}
}
}
The result of executing the sample program is as follows.
Throwable#getStackTrace()Get stack trace information using
sample.SampleClass1.method2(Main1.java:18)
sample.SampleClass1.method1(Main1.java:13)
sample.Main1.main(Main1.java:7)
Thread#getStackTrace()Get stack trace information using
java.lang.Thread.getStackTrace(Thread.java:1556)
sample.SampleClass1.method2(Main1.java:24)
sample.SampleClass1.method1(Main1.java:13)
sample.Main1.main(Main1.java:7)
If you use Thread # getStackTrace ()
, the stack trace information will be increased by one line.
It's not a big difference, so you can use either one.
There is an upper limit to the stack trace information that can be acquired.
In other words, the obtained StackTraceElement []
does not always contain all the stack trace information.
Let's check by running the following sample program.
Main2
package sample;
public class Main2 {
public static void main(String[] args) {
SampleClass2 sc = new SampleClass2();
sc.printStackTrace(200);
sc.printStackTrace(500);
sc.printStackTrace(1000);
sc.printStackTrace(2000);
sc.printStackTrace(3000);
}
}
class SampleClass2 {
public void printStackTrace(int stackCount) {
if (stackCount > 2) {
printStackTrace(stackCount - 1);
} else {
StackTraceElement[] ste = new Throwable().getStackTrace();
System.out.println("ste.length=" + ste.length);
}
}
}
The execution result depends on the JVM, but in my environment, the output is as follows.
ste.length=200
ste.length=500
ste.length=1000
ste.length=1024
ste.length=1024
You can see that the maximum number of stack trace information that can be acquired is 1024
.
In other words, it is not always possible to trace the caller back to the origin.
Recommended Posts