简体   繁体   English

异常和堆栈跟踪

[英]Exception and The Stack Trace

What happens when we say e.printStackTrace(); 当我们说e.printStackTrace();时会发生什么? ? Here e is any Exception . 这里e是任何Exception Does it stop the normal execution and actually remove the activation records from the thread stack to give the stack trace of the exception? 它会停止正常执行并实际上从线程堆栈中删除激活记录以提供异常的堆栈跟踪吗? Is it a good idea to use it in applications? 在应用程序中使用它是一个好主意吗?

It just prints stack trace that is already held by exception object to STDERR. 它只是将异常对象已经保存的堆栈跟踪打印到STDERR。 No side effects. 没有副作用。

e.printStackTrace();

e is instance of Throwable eThrowable实例

and printStackTrace() printStackTrace()

This method prints a stack trace for this Throwable object on the error output stream that is the value of the field System.err 此方法在错误输出流上打印此Throwable对象的堆栈跟踪,该输出是字段System.err的值

There's nothing particularly clever going on. 没有什么特别聪明的事情。 The Exception object contains a list of StackTraceElements , and it simply dumps them to stderr when the above is called. Exception对象包含一个StackTraceElements列表,在调用上述方法时,它只是将它们转储到stderr中。

Does it stop the normal execution 它会停止正常执行吗

No. 没有。

and actually remove the activation records from the thread stack to give the stack trace of the exception? 并实际上从线程堆栈中删除激活记录以提供异常的堆栈跟踪?

No. 没有。

The information has already been captured. 该信息被捕获。 This happens in the constructors for Throwable ; 这发生在Throwable的构造函数中; ie when you new an exception, not when you throw it. 即当你new异常,而不是当你throw它。 The Throwable constructor calls the fillInStackTrace() native method which takes a snapshot of the stack and stores the resulting StackTraceElement[] in a private variable that is used later when printing the stack trace. Throwable函数调用fillInStackTrace()本机方法,该方法获取堆栈快照并将结果StackTraceElement[]存储在私有变量中,此私有变量稍后在打印堆栈跟踪时使用。

(For the record, this is specified in the javadoc for the constructors of Throwable . (为便于记录,这是在Javadoc中为Throwable的构造函数指定的。

Is it a good idea to use it in applications? 在应用程序中使用它是一个好主意吗?

Well it is rather expensive and can produce a lot of output. 嗯,这是相当昂贵的,可以产生很多产出。 But if you need the stack trace for diagnostic purposes ... do it. 但是,如果出于诊断目的需要堆栈跟踪,请执行此操作。

As already said, there's no side effects and you won't introduce any issues per-se with using it in production code. 如前所述,没有副作用,并且在生产代码中使用它本身不会引起任何问题。 I wouldn't really advise it (in production code) however, simply because in most applications it's much better to use a logger to get finer control of exactly what's logged and where it's logged to. 但是,我并没有真正建议(在生产代码中使用),因为在大多数应用程序中,最好使用记录器更好地控制确切记录的内容和记录的位置。

The stack-trace is loaded via fillInStackTrace which is a native method that is called in the constructor of Throwable. 堆栈跟踪通过fillInStackTrace加载, fillInStackTrace是在Throwable的构造函数中调用的本机方法。 (Neat tip: this method can be overloaded as a NOP for "signal exceptions" which do not need the rather expensive call to get the stack). (整洁的提示:对于“信号异常”,此方法可以作为NOP重载,而无需花费相当昂贵的调用来获取堆栈)。

The "freeze" of the stack trace already exists for the Throwable object when it is "caught". 当Throwable对象被“捕获”时,堆栈跟踪的“冻结” 已经存在

As per the code for java.lang.Throwable shows that fillInStackTrace is called as the first action of the constructor. 按照java.lang.Throwable的代码,将fillInStackTrace调用为构造函数的第一个动作。 The array of StackTraceElement is for serialization support (this can also be set manually) and as a lazy cache. StackTraceElement数组用于序列化支持(也可以手动设置)并作为惰性缓存。

Even though that fillInStackTrace captures the trace it is not loaded into Java objects -- I suppose this allows the implementation to keep it "cheap" -- until it needs to be accessed as a sequence of StackTraceElement objects (eg for printStackTrace which is done in Java code). 即使fillInStackTrace捕获了加载到Java对象中的跟踪(我想这也使实现保持“便宜”),直到需要将其作为StackTraceElement对象序列访问为止(例如,对于printStackTrace ,这是在Java代码)。 The code for Throwable shows this better than I can explain :-) Throwable的代码比我可以解释的更好地展示了这一点:-)

Happy coding. 快乐的编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM