今天我意识到一些对我来说很奇怪的事情:当我这样做时,我注意到了
try {
doSomething();
} catch (Exception e) {
}
Run Code Online (Sandbox Code Playgroud)
它并不比我刚刚做的慢
doSomething();
Run Code Online (Sandbox Code Playgroud)
所以我运行了一个测试并写下了一些快速代码来证明我所看到的,代码基本上只是循环遍历一个名为doSomething()的函数很多次,一次没有,一次是try-catch包围它.如果您想自己测试它,那么这里是代码:
public class Main {
private static final long LOOPS = 1000000L;
public static final void main(String[] args)
{
System.out.println("Loop without try catch: "+loopWithoutTryCatch(LOOPS));
System.out.println("Loop with try catch: "+loopWithTryCatch(LOOPS));
}
public static long loopWithoutTryCatch(long loops)
{
long startTime = System.currentTimeMillis();
for (long i = 0L; i < loops; i++)
{
doSomething();
}
return System.currentTimeMillis()-startTime;
}
public static long loopWithTryCatch(long loops)
{
long startTime = System.currentTimeMillis();
for (long i = 0L; i < loops; i++)
{
try {
doSomething();
} catch (Exception e) {
}
}
return System.currentTimeMillis()-startTime;
}
public static void doSomething()
{
for (int i = 0; i < 250; i++)
{
if (i % 3 == 0)
{
i++;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我收到了以下输出:
Loop without try catch: 375
Loop with try catch: 373
Run Code Online (Sandbox Code Playgroud)
我很惊讶,所以我一次又一次地测试它,但我总是得到类似的结果,两种方式它在同一时间运行.
现在我的问题是:为什么?
我真的不明白它,据我所知try-catch在使用之前将资源写入某种表格以后 - 如果抛出任何异常 - 能够清理它并引用它在发生异常之前的值.
这应该至少花一些时间,不应该吗?我认为这可能是因为我选择的随机例子并没有恰当地代表它,而在我测试它的特定情况下它并没有减慢任何速度,但这对我来说似乎不太可能.
然后我想也许只需要这么短的时间就不会有那么少的执行量,所以我再次运行了测试程序,总共有1000万次循环,但我发现只是证明了我的意思已经发现:两次执行都需要几乎相同的时间.
那么是否有任何合理的解释是这种情况或只是try-catch的特定于示例的行为?
感谢您提前澄清.
throw
/ catch
blocks中的"慢度" 来自抛出和捕获异常的过程,而不是在为它们设置"陷阱"的过程中.抛出异常时,JVM必须
当没有发生这种情况时,JVM只是简单地说明堆栈上此级别的异常处理程序可用,并继续执行实际代码.
对于语言设计者来说,使功能免受惩罚是一个非常重要的目标:不应该要求程序员为他们不使用的东西付费.否则,程序员会试图跳过异常处理或回到使用状态代码的C方式,以便在这里和那里节省一些CPU周期,将异常拼写为一个特性.
从像你这样的代码生成的字节码遵循这种模式
1: invoke method
2: goto 4
3: store exception in catch block variable
// would contain handling code if there was any
4: return // or whatever comes after the try-catch
Exception table
if an exception of the type in catch block happens from 1 to 3, goto 3
Run Code Online (Sandbox Code Playgroud)
因此,try-catch
如果没有异常发生,基本上你添加的所有内容都是额外的goto.否则,JVM将在异常表中查找异常并匹配它发生的位置.然后它将准备Exception
并转到指定的任何指令索引.整个行动很重.
归档时间: |
|
查看次数: |
1179 次 |
最近记录: |