在Java中总是抛出异常异常 [英] Throwing always the same exception instance in Java

查看:173
本文介绍了在Java中总是抛出异常异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

总是告诉我Java异常处理是非常昂贵的。



我问这是否是一个很好的做法,在程序开始时创建一个特定类型的异常实例,而不创建一个新的异常实例,总是一样例外对象。



我只想举个例子。通用代码:

  if(!checkSomething(myObject))
抛出新的CustomException(你的对象无效) ;

替代方案:

 code> static CustomException MYEXP = new CustomException(您的对象无效); 

//其他地方
if(!checkSomething(myObject))
throw MYEXP;

当然,我在这里做一些假设:


  1. MyCustomException 没有参数

  2. 客户端代码,每当有良好的做法或不,是非常基于异常处理和重构不是一个选项。

所以问题是:


  1. 这是一个很好的做法吗?

  2. 这是否会损害一些JVM机制?

  3. 如果1是的,有表现增益的可能性吗? (我认为不是但不确定)

  4. 如果1和3是是,为什么不赞助作为实践?

  5. 如果1是否,为什么Martin Odersky在他对Scala的介绍中说,这是Scala在某些情况下的工作原理? (在28.30分钟,他告诉说,休息时间已经被抛出异常,观众说这是耗时的,他回答说这个例外并不是每次都创建的) Fosdem 2009

我希望这不是一个空闲/愚蠢的问题,我很好奇我认为异常处理中的实际成本是处理而不是创建。



编辑
添加FOSDEM演示文稿精确讨论的参考



免责声明:我的代码都没有像建议一样工作,我无意管理这样的异常,我只是在做一个假设的问题,这个好奇心是从视频生成的。我想:如果在Scala中完成,为什么不在Java中?

解决方案

不,不要这样做。昂贵的部分没有处理异常,它正在生成堆栈跟踪。不幸的是,堆栈跟踪也是有用的部分。如果你抛出一个保存的异常,你会传递一个误导的stacktrace。



可能是在Scala的实现中有这样的情况。 (也许他们正在做一些递归的事情,想要提前生成一个异常对象,以防它们内存不足,它们仍然可能会产生异常)。他们还有很多关于他们在做什么的信息,所以他们有更好的机会正确的但是,由JVM语言实现者进行的优化是一个非常特殊的例子。



所以你不会打破任何东西,除非你认为提供误导性的信息构成破损。对我来说似乎是一个很大的风险。



尝试托马斯·爱丁的建议,如何创建一个没有堆栈跟踪的异常似乎有效:

  groovy:000> MyException类扩展Exception {
groovy:001> public Throwable fillInStackTrace(){}}
===> true
groovy:000> e = new MyException()
===> MyException
groovy:000> Arrays.asList(e.stackTrace)
===> []

同时查看 /


由方法blowUp抛出的
的NullPointerException(这是一种RuntimeException)不会被main,
中的try语句捕获,因为NullPointerException不能分配给键入
BlewIt。这导致finally子句执行,之后
线程执行main,这是测试程序的唯一线程,
由于未捕获的异常而终止,通常会在打印时产生
异常名称和简单的回溯。但是,本规范不需要
的追溯。



强制回溯的问题是异常可以在一个点上创建
在程序中,并在之后抛出。将
存储在异常中是非常昂贵的,除非
实际上被抛出(在这种情况下,可能会生成跟踪,而
展开堆栈)。因此,我们不要求在每个
异常中返回追踪。



It was always told me that Java exception handling is quite expensive.

I'm asking if is it a good practice creating an exception instance of a specific type at the beginning of the program and without creating a new one, throwing always the same exception object.

I just want to make an example. Common code:

if (!checkSomething(myObject))
   throw new CustomException("your object is invalid");

alternative:

static CustomException MYEXP = new CustomException("your object is invalid");

//somewhere else
if (!checkSomething(myObject))
    throw MYEXP;

Of course, I'm doing some assumptions here:

  1. MyCustomException has no parameters
  2. client code, whenever is a good practice or not, is heavlily based on exception handling and refactoring is not an option.

So questions are:

  1. Is this a good practice?
  2. Does this damage some JVM mechanism?
  3. If 1 is yes, there is the possibility of a performance gain? (I think not, but not sure)
  4. If 1 and 3 are yes, why is not sponsored as practice?
  5. If 1 is no, why Martin Odersky told in his introduction to Scala that this is how Scala works in some cases? (At minute 28.30 he tolds that break is implemented has throwing an exception, audience says that this is time consuming and he replies that exception is not created every time)Fosdem 2009

I hope this is not a idle/stupid question, I'm curious about this. I think that real cost in exception handling is handling and not creation.

edit Added reference of precise discussion on FOSDEM presentation

disclaimer: none of my code works like proposed and I have no intention to manage exception like this, I'm just doing a "what-if" question and this curiosity is generated from the affermation that video. I thought: if it's done in Scala, why is not in Java?

解决方案

No, don't do that. The expensive part is not handling the exception, it is generating the stacktrace. Unfortunately the stacktrace is also the useful part. If you throw a saved exception you will be passing on a misleading stacktrace.

It could be that within the implementation of Scala there are situations where it makes sense to do this. (Maybe they are doing something recursive and want to generate an exception object upfront so in case they run out of memory they can still produce an exception.) They also have a lot of information about what they're doing so they have a better chance of getting it right. But optimizations made by JVM language implementors are a very special case.

So you wouldn't be breaking anything, unless you think providing misleading information constitutes breakage. It seems like a big risk to me.

Trying out Thomas Eding's suggestion for how to create an exception with no stacktrace seems to work:

groovy:000> class MyException extends Exception {
groovy:001>     public Throwable fillInStackTrace() {}}
===> true
groovy:000> e = new MyException()
===> MyException
groovy:000> Arrays.asList(e.stackTrace)
===> []

Also check out the JLS:

The NullPointerException (which is a kind of RuntimeException) that is thrown by method blowUp is not caught by the try statement in main, because a NullPointerException is not assignable to a variable of type BlewIt. This causes the finally clause to execute, after which the thread executing main, which is the only thread of the test program, terminates because of an uncaught exception, which typically results in printing the exception name and a simple backtrace. However, a backtrace is not required by this specification.

The problem with mandating a backtrace is that an exception can be created at one point in the program and thrown at a later one. It is prohibitively expensive to store a stack trace in an exception unless it is actually thrown (in which case the trace may be generated while unwinding the stack). Hence we do not mandate a back trace in every exception.

这篇关于在Java中总是抛出异常异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆