程序中没有一个方法“知道”它在堆栈中的位置。它所知道的只是它自己的小工作,它会做这件事并返回。那么当抛出异常并打印堆栈跟踪时,这是从哪里来的呢?
JVM 中的每个应用程序旁边是否隐式运行了一个单独的线程来监视程序的状态?或者 JVM 本身是否保存了这些信息,并且异常在抛出它们时会以某种方式从中提取数据?
如果是其中任何一种情况,是否可以使用某些调用来检索堆栈跟踪(从监视器线程或 JVM)而不抛出异常?
程序中没有一个方法“知道”它在堆栈中的位置。它所知道的只是它自己的小工作,它会做这件事并返回。那么当抛出异常并打印堆栈跟踪时,这是从哪里来的呢?
JVM 中的每个应用程序旁边是否隐式运行了一个单独的线程来监视程序的状态?或者 JVM 本身是否保存了这些信息,并且异常在抛出它们时会以某种方式从中提取数据?
如果是其中任何一种情况,是否可以使用某些调用来检索堆栈跟踪(从监视器线程或 JVM)而不抛出异常?
每个线程都有自己的stack
. 每个方法调用都会创建一个堆栈帧。如果任何方法的代码中发生错误,它将传播到调用者方法。这样 JVM 可以跟踪哪个方法产生了错误以及调用层次结构是什么。
如果您正确地观察堆栈跟踪,您将在顶部看到发生错误的方法,在底部看到层次结构。
斯坦福大学教授在youtube上有一个很棒的讲座,以了解它是如何工作的。我建议看一下。
注意:这是理论。如果您想了解 API 的工作原理,@Peter Lawrey 的回答可能会对您有所帮助。
它来自通过代码运行的 Thread 类。
Thread.dumpStack();
要查看它,您可以:
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
for (int i=0; i < trace.length; i++)
System.out.println("\tat " + trace[i]);
可以通过 . 知道方法所属的线程Thread.currentThread
。使用这个线程,您可以获得 StackTrace,因为 JVM 中的每个线程都有一个堆栈。此外,main
程序在main
线程中运行。
当您创建 Throwable 时(而不是在您抛出它时),它记录堆栈跟踪是与 Throwable 相关联的低级/隐藏方式。当您第一次调用 getStackTrace() 时,它会根据StackTraceElement[]
低级信息创建对象。它不会这么懒惰,因为堆栈跟踪通常不被使用。