问题:Java中的异常处理实际上是否很慢?
传统观念以及许多谷歌搜索结果表明,不应将特殊逻辑用于Java中的正常程序流程.通常有两个原因,
和
这个问题是关于#1.
例如,这个页面将Java异常处理描述为"非常慢",并将缓慢与异常消息字符串的创建联系起来 - "然后将此字符串用于创建抛出的异常对象.这并不快." Java中的有效异常处理这篇文章说"其原因在于异常处理的对象创建方面,从而使异常本身变得缓慢".另一个原因是堆栈跟踪生成减慢了它的速度.
我的测试(使用Java 1.6.0_07,Java HotSpot 10.0,在32位Linux上)表明异常处理并不比常规代码慢.我尝试在循环中运行一个执行一些代码的方法.在方法结束时,我使用布尔值来指示是返回还是抛出.这样实际处理是一样的.我尝试以不同的顺序运行方法并平均我的测试时间,认为它可能是JVM升温.在我的所有测试中,投掷至少与返回一样快,如果不是更快(最多快3.1%).我对我的测试错误的可能性持开放态度,但我没有看到代码示例,测试比较或过去一两年中显示Java中的异常处理的结果慢.
让我沿着这条路走下去的是我需要使用的API,它将异常作为正常控制逻辑的一部分.我想在他们的使用中纠正它们,但现在我可能无法做到.相反,我是否必须赞美他们的前瞻性思维?
在即时编译中的高效Java异常处理文章中,作者建议单独存在异常处理程序,即使没有抛出异常,也足以阻止JIT编译器正确优化代码,从而减慢它的速度.我还没有测试过这个理论.
总是告诉我Java异常处理非常昂贵.
我问的是,在程序开头创建特定类型的异常实例并且不创建新的异常实例是一个好习惯,总是抛出相同的异常对象.
我只想举个例子.常用代码:
if (!checkSomething(myObject))
throw new CustomException("your object is invalid");
Run Code Online (Sandbox Code Playgroud)
替代方案:
static CustomException MYEXP = new CustomException("your object is invalid");
//somewhere else
if (!checkSomething(myObject))
throw MYEXP;
Run Code Online (Sandbox Code Playgroud)
当然,我在这里做一些假设:
MyCustomException 没有参数所以问题是:
我希望这不是一个闲置/愚蠢的问题,我对此很好奇.我认为异常处理的实际成本是处理而不是创建.
编辑 添加了关于FOSDEM演示的精确讨论的参考
免责声明:我的代码都没有像提议的那样工作,我无意管理这样的异常,我只是在做一个"假设"问题,而这种好奇心是从视频的肯定中产生的.我想:如果在Scala中完成,为什么不在Java中呢?
(我搜索了类似的线程,找不到任何解决这个特定问题的东西,尽管有几个相似的例如这里和这里.)
我正在评估我们的应用程序的性能,我注意到我们正在获得一些IOExceptions"找不到资源".我不确定它发生了多少次(很大程度上取决于用户如何使用该应用程序),但它至少有十几个左右.
我假设异常通常是性能昂贵,文件I/O调用也是如此File.Exists().我知道在尝试加载文件之前检查文件是否存在总是很好的做法.我的问题是,如果我检查这个特定文件是否存在,我会看到多少性能提升?(再次,忽略"你应该这样做",我只是想了解性能).
选项1:
try
{
return (ResourceDictionary) Application.LoadComponent(uri);
}
catch (Exception)
{
//If it's not there, don't do anything
}
Run Code Online (Sandbox Code Playgroud)
这不会产生额外的IO调用,但有时会抛出并吞噬异常.
选项2:
if(File.Exists(uri))
{
return (ResourceDictionary) Application.LoadComponent(uri);
}
Run Code Online (Sandbox Code Playgroud) 我知道我可以NameNotFoundException从调用中捕获PackageManager.getPackageInfo或循环遍历PackageInfo返回的列表PackageManager.getInstalledPackages以了解是否安装了特定的软件包,但这两种方法看起来要么冗长乏味,要么很难看。在我的个人手机上,我安装了 300 多个软件包,所以我不想每次需要检查时都必须执行该操作。捕获异常作为执行应用程序逻辑的一种方式只会让我觉得整个人都错了。我是否在某处缺少 isPackageInstalled 方法,或者我是否只需要使用上述技术之一自己实现它?如果是后者,哪个会被认为是更快、资源密集度更低的选择?
java ×4
performance ×2
android ×1
benchmarking ×1
c# ×1
file-io ×1
jvm ×1
jvm-hotspot ×1
scala ×1
wpf ×1