usuario relanzar que propias por jerarquia excepciones definidas declaracion java

que - relanzar excepciones java



¿Por qué atrapar excepciones en Java, cuando puedes atrapar Throwables? (14)

¿Por qué no atraparlos a todos? Luego, conéctelos, al menos usted sabe que tiene un error. Así que es mejor capturar Throwable / s que Exception / s solamente.

Recientemente tuvimos un problema con una aplicación de servidor Java donde la aplicación arrojaba Errores que no fueron detectados porque Error es una subclase separada de Throwable y solo atrapamos Excepciones.

Solucionamos el problema inmediato atrapando Throwables en lugar de Excepciones, pero esto me hizo pensar en por qué querrías atrapar Excepciones, en lugar de Throwables, porque entonces te perderías los Errores.

Entonces, ¿por qué querrías capturar Excepciones, cuando puedes atrapar Throwables ?


De la documentación de la API de Java:

La clase Exception y sus subclases son una forma de Throwable que indica las condiciones que una aplicación razonable podría querer capturar.

Un Error es una subclase de Throwable que indica problemas graves que una aplicación razonable no debería intentar atrapar.

Los errores suelen ser de bajo nivel (p. Ej., Provocados por la máquina virtual) y la aplicación no debe capturarlos, ya que es posible que no se pueda continuar de forma razonable.


En general, sería razonable tratar de detectar los errores solo para poder informarlos correctamente.

Sin embargo, creo que hay casos en los que sería apropiado detectar un error y no informarlo. Me refiero a UnsatisfiedLinkError. En JAI, la biblioteca utiliza algunas bibliotecas nativas para implementar la mayoría de los operadores por razones de rendimiento; sin embargo, si la biblioteca no se carga (no existe, formato incorrecto, plataforma no compatible), la biblioteca seguirá funcionando porque caerá nuevamente en modo java solamente. .


Esta publicación no hará felices a las personas con "excepciones marcadas malas". Sin embargo, en lo que estoy basando mi respuesta es en cómo las excepciones de Java están destinadas a ser utilizadas según lo definido por las personas que crearon el lenguaje.

Tabla de referencia rápida:

  • Lanzable: nunca atrapes esto
  • Error - indica un error de VM - nunca capte esto
  • RuntimeException: indicó un error del programador, nunca captures esto
  • Excepción: nunca capte esto

La razón por la que no debe detectar Exception es que atrapa todas las subclases, incluida RuntimeException.

La razón por la que no debes atrapar a Throwable es que atrapa todas las subclases, incluidos Error y Excepción.

Hay excepciones (sin juego de palabras) a las "reglas" anteriores:

  • El código con el que está trabajando (de un tercero) arroja Throwable o Exception
  • Está ejecutando un código que no es de confianza y que podría hacer que su programa falle si se trata de una excepción.

Para el segundo, por lo general, es suficiente para envolver el código principal de manejo de eventos y los hilos con la captura en Throwable y luego verificar el tipo real de la excepción y tratarla según corresponda.


Hay al menos un caso en el que creo que debe atrapar una excepción arrojable o genérica: si está ejecutando un hilo separado para realizar una tarea, es posible que desee saber si el método "ejecutar" del hilo ha atrapado a algunos excepción o no. En ese caso, probablemente harás algo como esto:

public void run() { try { ... } catch(Throwable t) { threadCompletionError = t; } }

Realmente no estoy seguro de si es el mejor enfoque, pero funciona. Y estaba teniendo un error "ClassNotFound" planteado por la JVM, y es un error y no una excepción. Si dejo que se emita la excepción, no estoy seguro de cómo atraparla en el hilo de llamada (probablemente haya un método, pero aún no lo sé).

En cuanto al método ThreadDeath, no llame al método "Thread.stop ()". Llame a Thread.interrupt y tenga su hilo para verificar si fue interrumpido por alguien.


Muchas de las otras respuestas están mirando las cosas demasiado estrechamente.

Como dicen, si estás escribiendo un código de aplicación, no deberías atrapar Throwable. No puede hacer nada al respecto, por lo que es mejor permitir que el sistema circundante (JVM o framework) maneje estos problemas.

Sin embargo, si está escribiendo "código del sistema", como un marco u otro código de bajo nivel, entonces puede que quiera atrapar Throwable. El motivo es intentar informar la excepción, quizás en un archivo de registro. En algunos casos, su registro fallará, pero en la mayoría de los casos tendrá éxito y usted tendrá la información que necesita para resolver el problema. Una vez que haya realizado su intento de registro, deberá reiniciar, eliminar el hilo actual o salir de la JVM completa.


NO atrape Throwable o Error y generalmente no debería simplemente capturar una Exception genérica. Error generalmente son cosas de las que la mayoría de los programas razonables no pueden recuperarse. Si sabe lo que está sucediendo, es posible que pueda recuperarse de un error específico, pero en ese caso, debe detectar solo un error en particular y no todos los errores en general.

Una buena razón para no detectar el Error es debido a ThreadDeath . ThreadDeath es una ocurrencia bastante normal que teóricamente puede arrojarse desde cualquier lugar (otros procesos como la propia JVM pueden generarlo), y el objetivo es matar tu hilo. ThreadDeath es explícitamente un Error lugar de una Exception porque demasiadas personas atrapan todas las Exception . Si alguna vez ThreadDeath a ThreadDeath , debes volver a ThreadDeath para que tu hilo realmente muera.

Si tiene control sobre la fuente, probablemente debería reestructurarse para arrojar una Exception lugar de un Error . Si no lo hace, probablemente debería llamar al proveedor y quejarse. Error s deben reservarse solo para las cosas que son terminales y no hay forma posible de recuperarlas.


No tiene sentido capturar Error .

Los errores se utilizan para indicar que algo salió mal en su aplicación y debe reiniciarse.

Por ejemplo, un error común es

java.lang.OutOfMemoryError

No hay NADA que puedas hacer cuando eso suceda. Ya es demasiado tarde, la JVM ha agotado todas sus opciones para obtener más memoria, pero es imposible.

Vea esta otra respuesta para comprender más sobre los tres tipos de excepciones .


Normalmente, al programar, solo debe detectar una excepción específica (como IOException ). En muchos programas, puedes ver un muy alto nivel

try { ... } catch(Exception e) { ... }

Que capta todos los errores que podrían ser recuperables y todos aquellos que indican un error en su código, por ejemplo, InvalidArgumentException , NullPointerException . A continuación, puede enviar automáticamente un correo electrónico, mostrar un cuadro de mensaje o lo que quiera, ya que el JavaVM en sí mismo sigue funcionando bien.

Todo lo que se deriva de Error es algo muy malo, no se puede hacer nada en contra. La pregunta es si tiene sentido capturar un OutOfMemoryError o un VirtualMachineError . (Es un error en el JavaVM mismo, probablemente ni siquiera puede mostrar un cuadro de mensaje o enviar un correo electrónico)

Probablemente no deberías una clase derivada de Error , deberías derivar de Exception o RuntimeException .


Por lo general, los errores son problemas de los que no es posible recuperarse, como OutOfMemoryError . No hay nada que hacer al capturarlos, por lo que normalmente debería dejarlos escapar y derribar la máquina virtual.


Sé que puede ser contra-intuitivo, pero solo porque puedes atrapar todo tipo de Excepciones y Throwables y Errores no significa que debas hacerlo.

La captura excesivamente agresiva de java.lang.Exception puede provocar errores graves en las aplicaciones, ya que las Excepciones inesperadas nunca aparecen, nunca se detectan durante el desarrollo / prueba, etc.

Buena práctica: solo atrapar

  1. Excepciones que puedes manejar
  2. Excepciones que son necesarias para atrapar

Todo depende un poco de lo que vas a hacer con un Error una vez que lo hayas capturado. En general, la captura de errores probablemente no debería verse como parte de su flujo de excepción "normal". Si coges uno, no deberías pensar en "continuar como si nada hubiera pasado", porque JVM (y varias bibliotecas) usarán los errores como una forma de señalar que "algo realmente grave ha sucedido y necesitamos cerrar lo más pronto posible ". En general, es mejor escucharlos cuando te dicen que el final está cerca.

Otro problema es que la capacidad de recuperación o no de un Error puede depender de la máquina virtual en particular, que es algo sobre lo que puede o no tener control.

Dicho esto, hay algunos casos de esquina donde es seguro y / o deseable detectar errores, o al menos ciertas subclases:

  • Hay casos en los que realmente desea detener el curso normal de flujo: por ejemplo, si está en un Servlet, es posible que no desee que el controlador de excepción predeterminado del corredor de Servlet le anuncie al mundo que ha tenido un OutOfMemoryError, ya sea si no puedes recuperarte de eso.
  • Ocasionalmente, se producirá un error en los casos en que la JVM pueda recuperarse limpiamente de la causa del error. Por ejemplo, si se produce un OutOfMemoryError al intentar asignar una matriz, al menos en Hotspot, parece que puede recuperarse de forma segura. (Por supuesto, hay otros casos en los que se podría lanzar un OutOfMemoryError donde no sea seguro intentarlo y arar).

Así que la conclusión es: si atrapas Throwable / Error en lugar de Exception, debería ser un caso bien definido en el que sabes que estás "haciendo algo especial" .

Editar: Posiblemente esto es obvio, pero olvidé decir que, en la práctica, la JVM podría no invocar su cláusula catch en un error. Definitivamente, he visto Hotspot pasar por alto los intentos de capturar ciertos OutOfMemoryErrors y NoClassDefFoundError.



Voy a tomar una ruta ligeramente diferente de los demás.

Hay muchos casos en los que te gustaría atrapar a Throwable (principalmente para registrar / informar que sucedió algo malo).

Sin embargo , debes tener cuidado y volver a lanzar cualquier cosa con la que no puedas lidiar.

Esto es especialmente cierto en ThreadDeath.

Si alguna vez atrapas a Throwable, asegúrate de hacer lo siguiente:

try { ... } catch (SomeExceptionYouCanDoSomethingWith e) { // handle it } catch (ThreadDeath t) { throw t; } catch (Throwable t) { // log & rethrow }