堆栈跟踪是如何生成的?

3

在程序中,没有任何一种方法“知道”它在堆栈上的位置。它只知道自己的小任务,并执行该任务后返回。因此,当抛出异常并打印堆栈跟踪时,这是从哪里来的呢?

是否隐式存在一个与JVM中每个应用程序并行运行的单独线程,监视程序状态?还是JVM本身保存此信息,异常在抛出时从中提取数据?

如果是这两种情况之一,是否可能使用某些调用检索堆栈跟踪(从监视器线程或JVM中),而不需要抛出异常?

4个回答

5
每个线程都有自己的堆栈(stack)。每次方法调用都会创建一个堆栈帧。如果代码中的任何方法出现问题,错误将传递到调用方法。这样JVM就可以跟踪哪个方法生成了错误以及调用层次结构。
如果您仔细观察堆栈跟踪,您会看到出错方法在顶部,调用层次结构在底部。
有位斯坦福教授在YouTube上有一次精彩的演讲来解释它是如何运作的。我建议您观看一下。
注意:这是理论知识。如果您想了解API的工作原理,@Peter Lawrey的答案可能会对您有所帮助。

是的,我对这个理论非常感兴趣。 :) 这就是为什么我提出了这个问题,而不是出于任何特定的实际目的。 - asteri
好的,那么我的回答可能会给你一些线索,视频系列可以填补空白。 - kosa

4

这源于在代码中运行的Thread类。

Thread.dumpStack();

要查看它,你只需要:
    StackTraceElement[] trace = Thread.currentThread().getStackTrace();
    for (int i=0; i < trace.length; i++)
        System.out.println("\tat " + trace[i]);

3

你可以使用Thread.currentThread方法来了解一个方法所属的线程。使用这个线程,你可以获取堆栈跟踪信息,因为JVM中每个线程都有一个堆栈。而且,main程序运行在main线程中。


3

当你创建一个Throwable对象(不是当你抛出它时),它会以低级/隐藏的方式记录堆栈跟踪。当你第一次调用getStackTrace()方法时,它会从这些低级信息中创建StackTraceElement[]数组对象。由于堆栈跟踪经常不被使用,因此它不会立即创建。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接