java为什么启用某些异常的调试要慢得多?
考虑以下代码:
public class JMain {
private final static int forLength = 6;
private static void returnFromFor(int breakAt) {
try {
for (int j = 0; j < forLength; j++) {
if (j == breakAt) {
throw new Throwable("break");
}
}
} catch (Throwable ignored) {
}
}
public static void main(String args[]) {
long start = System.currentTimeMillis();
int iterations = 100000;
for (int i = 0; i < iterations; i++) {
returnFromFor(i % forLength);
}
long end = System.currentTimeMillis();
System.out.println(((Long) (end - start)).toString() + " ms");
}
}
当我在IntelliJ IDEA调试器中运行这段代码时,为java.lang.IllegalArgumentException
启用了异常断点,它运行得非常慢,在我的计算机上大约1800毫秒。当我在没有异常断点的情况下运行它,或者在为java.lang.UnsupportedOperationException
启用断点的情况下运行它时,速度大约快10倍
我的问题是:
为什么用
IllegalArgumentException
调试要比用UnsupportedOperationException
调试慢得多是JVM调试器还是IntelliJ导致的减速
我正在运行此操作的系统是:
- Windows x64
- IntelliJ IDEA Ultimate 2018.2
- JRE:1.8.0_152-release-1248-b8 amd64
注意:上面的代码演示了我在复杂Scala中遇到的问题。如果有人对更自然的Scala代码演示感兴趣,那么下面就是:
object Main extends App {
val forLength = 6
def returnFromFor(breakAt: Int): Unit = {
for (j <- 0 until forLength) {
if (j == breakAt) return
}
}
val start = System.currentTimeMillis()
val iterations = 100000
for (i <- 0 until iterations) {
returnFromFor(i%forLength)
}
val end = System.currentTimeMillis()
println(s"Duration ${end-start} ms")
}
# 1 楼答案
IDEA在加载目标异常类之前不会设置异常断点
UnsupportedOperationException
在程序的生命周期中从不加载。这就是为什么程序运行速度和没有断点时一样快IllegalArgumentException
是一个非常流行的类,它在JVM启动期间加载到JDK类库中的某个地方。在这种情况下,确实设置了异常断点,以便调试器接收有关程序中抛出的所有异常的通知