什么是jvm预分配例外?

nha*_*nha 5 java performance jvm jvm-hotspot

我在那里看到对预先分配的JVM异常的引用: - http://www.oracle.com/technetwork/java/javase/relnotes-139183.html - http://dev.clojure.org/display/community/Project+创意+ 2016

但寻找我只看到有关丢失堆栈跟踪的信息.什么是JVM分配的异常?这似乎是一种优化.

它是如何工作的,它有什么权衡取舍?

qww*_*sad 12

这些是在JVM开始时预先分配的异常.预分配的异常应该是隐式的:它们由JVM抛出,而不是throw new ... 在发生意外情况时抛出:解除引用空指针,访问具有负索引的数组等.

当方法过于频繁地(隐式地)抛出其中一个异常时,JVM会注意到并且在抛出已经预先分配的异常而没有堆栈跟踪的情况下替换每次抛出的异常分配.

这个机制是依赖于实现的,所以如果我们谈论热点,你可以在graphKit.cpp中找到这些异常的列表:

NullPointerException 
ArithmeticException
ArrayIndexOutOfBoundsException
ArrayStoreException
ClassCastException
Run Code Online (Sandbox Code Playgroud)

基本原理非常简单:抛出异常最昂贵的部分不是实际的抛出和堆栈展开,而是在异常中创建堆栈跟踪(它是对VM的相对较慢的调用,并且发生在异常构造函数中Throwable#fillInStackTrace).要查找具体数字和相对成本,您可以阅读热点性能工程师关于卓越性能的精彩文章.

有些人使用常规控制流的异常(请不要这样做)或出于性能考虑(通常是不正确的,例如看到这种流行的连接池框架),因此热点使这个[可能很糟糕]的代码快一点通过抛出已经创建的异常而没有堆栈跟踪(因此抛出了最昂贵的部分).

这种方法的缺点是现在你有无栈异常.这不是什么大不了的事:如果经常抛出这些隐式异常,你可能不会使用他们的堆栈跟踪.但是,如果这个假设不正确,那么您的日志中将没有跟踪的异常.为防止这种情况,您可以使用-XX:-OmitStackTraceInFastThrow