manejo - propagacion de excepciones en java
¿Qué es una excepción reprimida? (8)
Antes de Java7; Hay excepciones lanzadas en el código pero fueron ignoradas de alguna manera.
p.ej)
public class SuppressedExceptions {
public static void main(String[] args) throws Exception {
try {
callTryFinallyBlock();
} catch (Exception e) {
e.printStackTrace(); **//Only Finally Exception is Caught**
}
}
private static void callTryFinallyBlock() throws Exception {
try
{
throw new TryException(); **//This is lost**
}
finally
{
FinallyException fEx = new FinallyException();
throw fEx;
}
}
}
class TryException extends Exception {
}
class FinallyException extends Exception {
}
Un nuevo constructor y dos nuevos métodos se agregaron a la clase Throwable en JDK 7. Estos son los siguientes:
Throwable.getSupressed(); // Returns Throwable[]
Throwable.addSupressed(aThrowable);
con este nuevo enfoque, podemos manejar esas excepciones suprimidas también.
public class SuppressedExceptions {
public static void main(String[] args) throws Exception {
try {
callTryFinallyBlock();
} catch (Exception e) {
e.printStackTrace();
for(Throwable t: e.getSuppressed())
{
t.printStackTrace();
}
}
}
private static void callTryFinallyBlock() throws Exception {
Throwable t = null;
try
{
throw new TryException();
}
catch (Exception e) {
t = e;
}
finally
{
FinallyException fEx = new FinallyException();
if(t != null)fEx.addSuppressed(t);
throw fEx;
}
}
}
class TryException extends Exception {
}
class FinallyException extends Exception {
}
En Java7 try-with-resources; la excepción en AutoCloseable :: close () se agrega como excepción suprimida de manera predeterminada junto con la excepción try.
También consciente de que esto es diferente de las excepciones encadenadas (se introdujeron con JDK 1.4 y estaban destinadas a permitir rastrear fácilmente las relaciones causales entre excepciones).
Un comentario (por parte del usuario soc ) sobre una answer a una pregunta sobre la optimización de la llamada final, menciona que Java 7 tiene una nueva característica llamada "excepciones suprimidas", debido a "la adición de ARM" (¿soporte para CPU ARM?).
¿Qué es una "excepción suprimida" en este contexto? En otros contextos, una "excepción suprimida" sería una excepción que fue atrapada y luego ignorada (raramente una buena idea); esto es claramente algo diferente.
Creo que esto tiene que ver con la "instalación de excepción encadenada". Afectará cómo esta instalación maneja una excepción a medida que evoluciona el seguimiento de la pila. Con el tiempo, las excepciones que son parte de un grupo de excepción encadenada pueden ser suprimidas. Mira la documentación de Throwable para más detalles.
Entrando al código a continuación:
public class MultipleExceptionsExample {
static class IOManip implements Closeable{
@Override
public void close() {
throw new RuntimeException("from IOManip.close");
}
}
public static void main(String[] args) {
try(IOManip ioManip = new IOManip()){
throw new RuntimeException("from try!");
}catch(Exception e){
throw new RuntimeException("from catch!");
}finally{
throw new RuntimeException("from finally!");
}
}
}
Con todas las líneas obtendrás: java.lang.RuntimeException: from finally!
final java.lang.RuntimeException: from finally!
Al eliminar finally
bloque obtendrás: java.lang.RuntimeException: from catch!
Al quitar el bloqueo catch
obtendrás:
Exception in thread "main" java.lang.RuntimeException: from try!
Suppressed: java.lang.RuntimeException: from IOManip.close
Para aclarar la cita en la respuesta de Jon, solo se puede arrojar una excepción mediante un método (por ejecución), pero es posible, en el caso de un try-with-resources
, lanzar múltiples excepciones. Por ejemplo, uno podría ser arrojado al bloque y otro podría ser arrojado desde el implícito finally
provisto por el try-with-resources
.
El compilador tiene que determinar cuál de estos arrojar "realmente". Elige arrojar la excepción planteada en el código explícito (el código en el bloque try
) en lugar del arrojado por el código implícito (el bloque finally
). Por lo tanto, la excepción lanzada en el bloque implícito se suprime (ignora). Esto solo ocurre en el caso de múltiples excepciones.
También puede suprimir Excepciones en Java 6 (un pequeño truco involucrado),
Creé una utilidad que maneja de forma transparente la supresión de excepciones en Java 1.6 y Java 1.7. Puede encontrar la implementación here
Todo lo que necesitas es llamar:
public static <T extends Throwable> T suppress(final T t, final Throwable suppressed)
para suprimir una excepción, y
public static Throwable [] getSuppressed(final Throwable t) {
para obtener las excepciones suprimidas de una excepción, en caso de que alguien todavía use Java 1.6
Las excepciones suprimidas son excepciones adicionales que se producen dentro de una declaración try-with-resources ( try-with-resources ) cuando se cierran los recursos de AutoCloseable
. Debido a que pueden ocurrir varias excepciones al cerrar los recursos de AutoCloseable
, se adjuntan excepciones adicionales a una excepción principal como excepciones suprimidas .
Al observar el bytecode de una pieza de código de ejemplo try-with-resources, los manejadores de excepciones JVM estándar se utilizan para acomodar la semántica try-with-resources.
ARM - Automatic Resource Management (Introducido desde Java 7)
Tome un ejemplo muy simple
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
Ahora si la función readLine()
arroja Exception y luego incluso la función close()
[in finally block] arroja una excepción, a la última se le da más prioridad y se devuelve a la función de llamada. En este caso, la Exception thrown by the readLine() method is ignored/suppressed
. Puede encadenar la excepción causante en su excepción y volver a lanzar su excepción del bloque finally.
Desde que se proporcionó la funcionalidad java 7
para recuperar excepciones suprimidas. Puede llamar a la función public final java.lang.Throwable[] getSuppressed()
en el objeto arrojado atrapado para ver las excepciones suprimidas.
Por ejemplo
static String readFirstLineFromFileWithFinallyBlock(String path)
throws Exception {
try (BufferedReader br = new BufferedReader(new FileReader(path));) {
return br.readLine();
}
}
Ahora si br.readLine();
la línea arroja la Exception1
y luego permite lanzar Exception2
mientras se cierra el recurso [Imagínese que esto sucede en un bloque final implícito que crea la declaración try-with-resource], luego Exception1 suprime Exception2.
Pocos puntos a tener en cuenta aquí -
- Si el bloque try-with-resource arroja una excepción, es decir, mientras se ejecuta el recurso, el bloqueo try no se ejecutará y se lanzará la misma excepción.
- Si la instanciación del recurso es exitosa, intente bloquear arroja una excepción y se lanza una excepción mientras se cierra el recurso, luego se lanza la excepción mientras el recurso de cierre es suprimido por la excepción lanzada desde el bloque try.
- Si proporciona un bloque explícito finalmente y se lanza una excepción desde ese bloque, suprimirá todas las demás excepciones. (Este bloque finalmente explícito se ejecuta después de que se cierren los recursos)
He compilado la mayoría de los escenarios posibles con fragmentos de código y salida en la siguiente publicación.
Supresión de excepciones en java 7
Espero que ayude.
Creo que el comentarista se está refiriendo a es una excepción que es semi-ignorada cuando se lanza dentro del bloque finally
implícito de un bloque try-with-resources , en el contexto de una excepción existente lanzada desde el bloque try
:
Se puede lanzar una excepción del bloque de código asociado con la declaración try-with-resources. En el ejemplo writeToFileZipFileContents, se puede lanzar una excepción desde el bloque try, y se pueden lanzar hasta dos excepciones desde la declaración try-with-resources cuando intenta cerrar los objetos ZipFile y BufferedWriter. Si se lanza una excepción desde el bloque try y se lanzan una o más excepciones de la declaración try-with-resources, entonces esas excepciones lanzadas desde la sentencia try-with-resources son suprimidas, y la excepción arrojada por el bloque es la excepción eso es arrojado por el método writeToFileZipFileContents. Puede recuperar estas excepciones suprimidas llamando al método Throwable.getSuppressed de la excepción lanzada por el bloque try.
(Eso es citar una sección llamada "Excepciones suprimidas" de la página vinculada).