如何理解StackTraceElement工作原理?为何需置于方法链末尾打印完整调用链?
关于Java调用栈与StackTraceElement的疑问解答
首先得明确:调用栈是动态变化的,它记录的是程序执行到当前时刻时,正在调用(还没执行完)的方法链。
第一个代码示例的执行逻辑
程序运行时,方法调用顺序是:main() → method1() → method2() → method3()
当执行到method3()里的Thread.currentThread().getStackTrace()时,此时调用栈的状态是:
getStackTrace()(Thread类的内部方法)method3()(当前正在执行的方法)method2()(调用method3的方法,还没执行完)method1()(调用method2的方法,还没执行完)main()(最初的入口方法,还没执行完)
所以遍历这个栈数组时,就能打印出整个调用链里的所有方法。
对应的代码:
public class ExceptionPrzyklad { public static void main(String[] args) { method1(); } public static void method1() { method2(); } public static void method2() { method3(); } public static void method3() { StackTraceElement[] stackTraceELement = Thread.currentThread().getStackTrace(); for (StackTraceElement element : stackTraceELement) { System.out.println(element.getMethodName()); } } }
第二个代码示例的问题所在
在main()开头就调用getStackTrace()时,程序才刚进入main(),还没执行method1()的调用。此时调用栈的状态只有:
getStackTrace()(Thread类的内部方法)main()(当前正在执行的方法)
这时候栈里根本没有method1()、method2()、method3()——这些方法还没被调用,自然打印不出来。等后面调用这些方法时,之前的getStackTrace()已经执行完毕,没法再捕获到后续的调用栈状态。
对应的代码:
public class ExceptionPrzyklad { public static void main(String[] args) { StackTraceElement[] stackTraceELement = Thread.currentThread().getStackTrace(); for (StackTraceElement element : stackTraceELement) { System.out.println(element.getMethodName()); } method1(); } public static void method1() { method2(); } public static void method2() { method3(); } public static void method3() { } }
简单总结:getStackTrace()只能捕获调用它的那个时刻的调用栈状态。要想获取完整的main()→method1()→method2()→method3()调用链,必须在这个链的最末端(也就是method3()执行时)调用它,此时整个链的方法都还在栈里(未执行完毕)。
内容的提问来源于stack exchange,提问作者CodingNoob98
相关产品推荐
相关产品推荐

