JVM 啥时候开始忽略堆栈跟踪?
Posted
技术标签:
【中文标题】JVM 啥时候开始忽略堆栈跟踪?【英文标题】:When does JVM start to omit stack traces?JVM 什么时候开始忽略堆栈跟踪? 【发布时间】:2019-11-04 15:06:09 【问题描述】:我已经搜索了很多关于该主题的内容。但没有具体的解决方案/指南。
来自docs,
某些虚拟机可能会在某些情况下省略一个或 来自堆栈跟踪的更多堆栈帧。在极端情况中,一个 没有与此相关的堆栈跟踪信息的虚拟机 允许 throwable 从此方法返回一个长度为零的数组。
有人可以阐明这可能/将会发生的条件吗?
我知道如果一遍又一遍地产生相同的堆栈跟踪,就会发生这种情况(计数没有硬性规定,AFAIK- 否则请纠正我)。但这不是有一个明确的行为吗?
另外,根据this,传递-XX:-OmitStackTraceInFastThrow
将确保我的StackTrace
不会丢失。在生产机器上总是这样做不是明智的吗?
【问题讨论】:
性能。如果它一遍又一遍地生成相同的堆栈跟踪,就会发生这种情况。 回复:极端情况。我认为如果 JVM 正在生成内存不足的错误,例如,它甚至可能没有足够的内存来构建堆栈跟踪,所以它必须是空的。 如果内存消耗如此严重,那么抛出 OOM 比“静默”抑制堆栈跟踪要好,对吧? "在生产机器上总是这样做不是很明智吗?" 不。我们的生产机器已启用此功能。我们更关心性能提升,而不是每次都获取完整的堆栈跟踪。如果省略,则表示已经生成。要获取完整的堆栈跟踪,只需转到日志中的第一次出现。 我不明白你的意思。总是抛出 OOM 异常。只是抛出的OOM是否包含堆栈跟踪。如果没有内存来生成它,别无选择,只能扔掉它。 【参考方案1】:OmitStackTraceInFastThrow
是C2 编译代码中的一项优化,可以在没有堆栈跟踪的情况下引发某些隐式异常。
优化仅适用于隐式异常,即由 JVM 本身引发的异常,而不是由用户代码引发的异常。这些隐含的例外是:
NullPointerException
算术异常
ArrayIndexOutOfBoundsException
ArrayStoreException
ClassCastException
仅当 JVM 知道该特定位置之前已发生异常时,才会省略堆栈跟踪。
因此,在 HotSpot JVM 中,如果满足以下所有条件,则异常不会有堆栈跟踪: 1) 抛出方法是热的,即由 C2 编译; 2)这是一个隐含的例外,例如NPE 由 obj.method()
抛出,但不是由 throw new NullPointerException()
抛出; 3) 至少第二次抛出异常。
优化的目的是消除在快速路径上重复抛出隐式异常的那些(可以说是罕见的)情况对性能的影响。在我看来,这不是一个正常的情况。异常,尤其是隐式异常,通常表示需要修复的错误情况。从这个意义上说,禁用-XX:-OmitStackTraceInFastThrow
是可以的。例如。在我们的生产环境中,我们总是禁用它,它为我们节省了很多调试时间。但是,我承认,如果存在这样的优化,在某些情况下它有助于解决性能问题。
TL;DR 添加-XX:-OmitStackTraceInFastThrow
选项确实是个好主意,除非您的应用程序的热路径上有许多隐式异常。
【讨论】:
除了快速投掷功能之外,还有其他情况,like insufficient memory 可能导致投掷物没有堆栈跟踪。以上是关于JVM 啥时候开始忽略堆栈跟踪?的主要内容,如果未能解决你的问题,请参考以下文章
有啥方法可以在 Sql Profiler 或类似工具中获取 .net 堆栈跟踪?