Java 异常和堆栈跟踪
当我们说Java 异常和堆栈跟踪,java,exception,Java,Exception,当我们说e.printStackTrace()时会发生什么?这里的e是任何异常。它是否会停止正常执行,并实际从线程堆栈中删除激活记录,以提供异常的堆栈跟踪?在应用程序中使用它是一个好主意吗?e.printStackTrace() e是 及 此方法在错误输出流(即字段System.err的值)上打印此可丢弃对象的堆栈跟踪 它只是将异常对象已经持有的堆栈跟踪打印到STDERR。没有副作用 没有什么特别聪明的事情发生。Exception对象包含一个列表,当调用上述函数时,它会将它们简单地转储到stde
e.printStackTrace()时会发生什么代码>?这里的e
是任何异常
。它是否会停止正常执行,并实际从线程堆栈中删除激活记录,以提供异常的堆栈跟踪?在应用程序中使用它是一个好主意吗?e.printStackTrace()代码>
e
是
及
此方法在错误输出流(即字段System.err的值)上打印此可丢弃对象的堆栈跟踪
它只是将异常对象已经持有的堆栈跟踪打印到STDERR。没有副作用 没有什么特别聪明的事情发生。Exception
对象包含一个列表,当调用上述函数时,它会将它们简单地转储到stderr。正如前面所说的,在生产代码中使用它不会产生任何副作用,也不会带来任何问题。不过,我并不建议(在生产代码中)这样做,因为在大多数应用程序中,最好使用记录器来更好地精确控制记录的内容和记录到的位置。堆栈跟踪是通过Throwable构造函数中调用的本机方法加载的。(简洁提示:此方法可以作为NOP重载,用于“信号异常”,而不需要非常昂贵的调用来获取堆栈)
当可丢弃对象被“捕获”时,堆栈跟踪的“冻结”已经存在。
根据的代码显示,构造函数的第一个操作调用了fillInStackTrace
。stackTraceeElement
的数组用于序列化支持(也可以手动设置)和作为延迟缓存
即使fillInStackTrace
捕获了跟踪,它也不会加载到Java对象中——我想这允许实现保持它的“便宜”——直到它需要作为StackTraceElement
对象序列访问(例如,对于printStackTrace
,这是在Java代码中完成的)。Throwable的代码比我所能解释的更好地说明了这一点:-)
快乐编码
它会停止正常的执行吗
没有
并实际从线程堆栈中删除激活记录以提供异常的堆栈跟踪
没有
信息已经被捕获。这发生在Throwable的构造函数中;i、 e.当您新建
异常时,而不是当您抛出它时。Throwable
构造函数调用fillInStackTrace()
本机方法,该方法获取堆栈快照,并将生成的StackTraceElement[]
存储在私有变量中,稍后打印堆栈跟踪时使用该变量
(对于记录,这在javadoc中为的构造函数指定
在应用程序中使用它是一个好主意吗
嗯,它相当昂贵,并且可以产生大量输出。但是如果您需要堆栈跟踪用于诊断目的,那么就这样做。标准错误,而不是标准输出。虽然在大多数情况下这并不重要。堆栈跟踪是创建异常时的线程堆栈,而不是打印/记录异常的位置。一个小的副作用是由于性能原因,ack跟踪在使用之前不会填充,通常不会使用堆栈跟踪。它存储在别处,但在代码中使用之前,您无法在调试器中看到它。@Peter Lawrey在“本机某处”中的其他位置,但“本机某处”通常填充有fillInStackTrace
,它已经具有记录堆栈的“成本”。这只是将堆栈从本地拉到被绕过的StackTraceElement对象中的“成本”。它比这更聪明一点;-)私有数组用于序列化和缓存(它在fillInStackTrace上是延迟加载和“空值”的)。这是(sun)JVM/JRE,可能会更高效地存储堆栈帧,并通过本机方法公开它们(我猜是以更高效的非对象形式)。请参见+1。但是,fillInStackTrace并没有填充Sun JVM/JRE中的私有数组——它是一个本机方法,它也会这样做(在本机端)GETSTACKTROW将本地数据撤回并将其存储到私有数组中。@ PST -大多数人会认为 fIListCasTrace](/Cuff>)(广义上)是在做这项工作。此外,私有本机方法调用是特定于平台的实现细节。