我在那里看到了对预分配 JVM 异常的引用: - http://www.oracle.com/technetwork/java/javase/relnotes-139183.html - http://dev.clojure.org/display/community/Project+Ideas+2016
但是在查找时,我只看到有关丢失堆栈跟踪的信息。 什么是 JVM 分配的异常?这似乎是一种优化。
它是如何工作的,它的权衡是什么?
最佳答案
这些是在 JVM 启动时预先分配的异常。
预分配异常应该是隐式:它们由 JVM 抛出,而不是 throw new ...
当意外情况发生时:解引用空指针、访问具有负索引的数组等。
当方法开始(隐式地)抛出这些异常之一时 too frequently ,JVM 会注意到这一点,并将每次抛出时的异常分配替换为抛出没有堆栈跟踪的已预先分配的异常。
此机制依赖于实现,因此如果我们谈论热点,您可以在 graphKit.cpp 中找到这些异常的列表。 :
NullPointerException
ArithmeticException
ArrayIndexOutOfBoundsException
ArrayStoreException
ClassCastException
基本原理很简单:抛出异常的最昂贵的部分不是实际的抛出和堆栈展开,而是在异常中创建堆栈跟踪(这是对 VM 的相对较慢的调用,并且通过 Throwable 在异常构造函数中发生#fillInStackTrace
)。要查找具体数字和相关成本,您可以阅读热点性能工程师关于 exceptional performance 的精彩文章.
有些人将异常用于常规控制流(请不要那样做)或出于性能考虑(这通常是不正确的,例如参见 this 一种流行的连接池框架),所以热点使这个 [可能不好]通过在没有堆栈跟踪的情况下抛出已经创建的异常来加快代码速度(因此消除了抛出最昂贵的部分)。
这种方法的缺点是现在您会遇到无堆栈跟踪的异常。这没什么大不了的:如果这些隐式异常被频繁抛出,您可能不会使用它们的堆栈跟踪。但是,如果这个假设不正确,您将在日志中看到没有痕迹的异常。为防止这种情况,您可以使用 -XX:-OmitStackTraceInFastThrow
关于java - 什么是 jvm 预分配异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42115284/