栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

异常对Java性能的影响是什么?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

异常对Java性能的影响是什么?

取决于异常的实现方式。最简单的方法是使用setjmp和longjmp。这意味着将CPU的所有寄存器都写入堆栈(这已经花费了一些时间),并且可能需要创建一些其他数据…所有这些都已经在try语句中发生。throw语句需要展开堆栈并恢复所有寄存器的值(以及VM中可能的其他值)。因此try和throw都同样缓慢,而且也相当慢,但是,如果没有抛出异常,则在大多数情况下退出try块几乎不会花费任何时间(因为所有内容都放在堆栈中,如果该方法存在,则堆栈会自动清除)。

Sun和其他公司认识到,这可能不是最佳选择,并且随着时间的流逝,虚拟机当然会越来越快。还有另一种实现异常的方法,它可以使尝试本身快如闪电(实际上一般而言,尝试都不会发生任何事情-当类由VM加载时,所有需要发生的事情都已经完成了),并且抛出异常的速度也不太慢。我不知道哪个JVM使用这种更好的新技术…

…但是你是否使用Java编写,因此以后的代码只能在一个特定系统上的一个JVM上运行?由于它是否可以在任何其他平台或任何其他JVM版本(可能是任何其他供应商的版本)上运行,谁说他们也使用快速实现?快速的比慢的更复杂,并且在所有系统上都不容易实现。你想保持便携性吗?然后,不要依赖快速的异常。

在try块中执行的操作也有很大的不同。如果你打开一个try块,并且从不从该try块中调用任何方法,则try块将非常快,因为JIT实际上可以像简单的goto一样处理throw。如果抛出异常(它只需要跳转到catch处理程序),它既不需要保存堆栈状态,也不需要取消堆栈。但是,这不是你通常执行的操作。通常,你打开一个try块,然后调用一个可能引发异常的方法,对吗?即使你仅在方法中使用try块,这将是哪种方法,而不会调用任何其他方法?它会只计算一个数字吗?那你需要例外吗?有许多更优雅的方法来调节程序流。除了简单的数学运算外,

请参阅以下测试代码:

public class Test {    int value;    public int getValue() {        return value;    }    public void reset() {        value = 0;    }    // Calculates without exception    public void method1(int i) {        value = ((value + i) / i) << 1;        // Will never be true        if ((i & 0xFFFFFFF) == 1000000000) { System.out.println("You'll never see this!");        }    }    // Could in theory throw one, but never will    public void method2(int i) throws Exception {        value = ((value + i) / i) << 1;        // Will never be true        if ((i & 0xFFFFFFF) == 1000000000) { throw new Exception();        }    }    // This one will regularly throw one    public void method3(int i) throws Exception {        value = ((value + i) / i) << 1;        // i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both        // an AND operation between two integers. The size of the number plays        // no role. AND on 32 BIT always ANDs all 32 bits        if ((i & 0x1) == 1) { throw new Exception();        }    }    public static void main(String[] args) {        int i;        long l;        Test t = new Test();        l = System.currentTimeMillis();        t.reset();        for (i = 1; i < 100000000; i++) { t.method1(i);        }        l = System.currentTimeMillis() - l;        System.out.println( "method1 took " + l + " ms, result was " + t.getValue()        );        l = System.currentTimeMillis();        t.reset();        for (i = 1; i < 100000000; i++) { try {     t.method2(i); } catch (Exception e) {     System.out.println("You'll never see this!"); }        }        l = System.currentTimeMillis() - l;        System.out.println( "method2 took " + l + " ms, result was " + t.getValue()        );        l = System.currentTimeMillis();        t.reset();        for (i = 1; i < 100000000; i++) { try {     t.method3(i); } catch (Exception e) {     // Do nothing here, as we will get here }        }        l = System.currentTimeMillis() - l;        System.out.println( "method3 took " + l + " ms, result was " + t.getValue()        );    }}

结果:

method1 took 972 ms, result was 2method2 took 1003 ms, result was 2

method3 took 66716 ms, result was 2
try块的速度太慢,无法排除诸如后台进程之类的混淆因素。但是捕获块杀死了所有东西并使它变慢了66倍!

就像我说的,如果将try / catch放在同一方法(method3)中并全部抛出,结果将不会那么糟,但这是我不依赖的特殊JIT优化。即使使用此优化,抛出也仍然很慢。所以我不知道你要在这里做什么,但是绝对有比使用try / catch / throw更好的方法。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/390503.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号