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