JVM 什么时候开始省略堆栈跟踪?
When does JVM start to omit stack traces?
我已经搜索了很多有关该主题的内容。但是没有具体的 solution/guide 存在。
来自docs,
Some virtual machines may, under some circumstances, omit one or
more stack frames from the stack trace. In the extreme case, a
virtual machine that has no stack trace information concerning this
throwable is permitted to return a zero-length array from this method.
有人可以阐明这种 may/will 发生的条件吗?
我知道如果一遍又一遍地生成相同的堆栈跟踪就会发生这种情况(没有关于计数的硬性规定,AFAIK - 否则请纠正我)。但这不应该有一个明确的行为吗?
此外,根据 this,传递 -XX:-OmitStackTraceInFastThrow
将确保我的 StackTrace
不会丢失。在生产机器上这样做不是明智的吗?
OmitStackTraceInFastThrow
是 C2 编译的 代码中的优化,用于在没有堆栈跟踪的情况下抛出某些隐式异常。
- 优化仅适用于隐式 异常,即 JVM 本身抛出的异常,而不是用户代码抛出的异常。这些隐式异常是:
- 空指针异常
- 算术异常
- ArrayIndexOutOfBoundsException
- ArrayStoreException
- ClassCastException
- 仅当 JVM 知道在此特定位置早些时候发生过异常时,才会省略堆栈跟踪。
因此,在HotSpot JVM 中,如果满足以下所有条件,异常将不会有堆栈跟踪: 1) 抛出方法是热的,即由C2 编译; 2)这是一个隐含的异常,例如obj.method()
抛出的 NPE,而不是 throw new NullPointerException()
抛出的 NPE; 3) 至少第二次抛出异常
优化的目的是消除在快速路径上重复抛出隐式异常时的那些(可以说是罕见的)情况的性能影响。在我看来,这不是正常情况。异常,尤其是隐式异常,通常表示需要修复的错误情况。从这个意义上说,禁用 -XX:-OmitStackTraceInFastThrow
是可以的。例如。在我们的生产环境中,我们总是禁用它,它为我们节省了很多调试时间。但是,我承认如果存在这样的优化,在某些情况下它有助于解决性能问题。
TL;DR 添加 -XX:-OmitStackTraceInFastThrow
选项确实是个好主意,除非您的应用程序中的热路径上存在许多隐式异常。
我已经搜索了很多有关该主题的内容。但是没有具体的 solution/guide 存在。
来自docs,
Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this throwable is permitted to return a zero-length array from this method.
有人可以阐明这种 may/will 发生的条件吗?
我知道如果一遍又一遍地生成相同的堆栈跟踪就会发生这种情况(没有关于计数的硬性规定,AFAIK - 否则请纠正我)。但这不应该有一个明确的行为吗?
此外,根据 this,传递 -XX:-OmitStackTraceInFastThrow
将确保我的 StackTrace
不会丢失。在生产机器上这样做不是明智的吗?
OmitStackTraceInFastThrow
是 C2 编译的 代码中的优化,用于在没有堆栈跟踪的情况下抛出某些隐式异常。- 优化仅适用于隐式 异常,即 JVM 本身抛出的异常,而不是用户代码抛出的异常。这些隐式异常是:
- 空指针异常
- 算术异常
- ArrayIndexOutOfBoundsException
- ArrayStoreException
- ClassCastException
- 仅当 JVM 知道在此特定位置早些时候发生过异常时,才会省略堆栈跟踪。
因此,在HotSpot JVM 中,如果满足以下所有条件,异常将不会有堆栈跟踪: 1) 抛出方法是热的,即由C2 编译; 2)这是一个隐含的异常,例如obj.method()
抛出的 NPE,而不是 throw new NullPointerException()
抛出的 NPE; 3) 至少第二次抛出异常
优化的目的是消除在快速路径上重复抛出隐式异常时的那些(可以说是罕见的)情况的性能影响。在我看来,这不是正常情况。异常,尤其是隐式异常,通常表示需要修复的错误情况。从这个意义上说,禁用 -XX:-OmitStackTraceInFastThrow
是可以的。例如。在我们的生产环境中,我们总是禁用它,它为我们节省了很多调试时间。但是,我承认如果存在这样的优化,在某些情况下它有助于解决性能问题。
TL;DR 添加 -XX:-OmitStackTraceInFastThrow
选项确实是个好主意,除非您的应用程序中的热路径上存在许多隐式异常。