programador - propagacion de excepciones en java
¿En qué circunstancias no se ejecutará un bloque finally{}? (9)
Bucle infinito en el bloque try
.
¿ RAM dañada ? ¿El programa ya no se ejecuta como está escrito? De hecho, he depurado eso una vez en una máquina DOS.
En un bloque de try{} ... catch{} ... finally{}
Java try{} ... catch{} ... finally{}
, el código dentro del finally{}
generalmente se considera "garantizado" para ejecutarse independientemente de lo que ocurra en la prueba / captura. Sin embargo, conozco al menos dos circunstancias bajo las cuales no se ejecutará:
- Si se
System.exit(0)
; o, - si se lanza una excepción hasta la JVM y se produce el comportamiento predeterminado (es decir,
printStackTrace()
y salir)
¿Hay algún otro comportamiento del programa que impida que el código en un bloque final finally{}
se ejecute? ¿Bajo qué condiciones específicas se ejecutará o no el código?
EDITAR: Como señaló NullUserException, el segundo caso en realidad no es cierto. Pensé que era porque el texto en el error estándar se imprimía después de eso en la salida estándar, evitando que se viera el texto sin desplazarse hacia arriba. :) Disculpas.
Creo que cuando JVM sale de repente debido a alguna razón, eso puede ser una causa por la cual el control no entrará en el bloque final y nunca se ejecutará.
Existe la posibilidad de ejecución parcial cuando finalmente se lanza una excepción (o conduce a un error)
Las únicas veces que finalmente no se llamarán son:
si el poder se apaga
- si llamas a System.exit ()
- si la JVM se bloquea primero
- Si hay un bucle infinito en el bloque try
- si el poder se apaga
Otra posible instancia de un bloque final que nunca se ejecuta se debe a un diseño en el que el método devuelto antes de que se ingresara el bloque try, como en los casos de algún código muy malo que he visto de vez en cuando:
public ObjectOfSomeType getMeAnObjectOfSomeType() throws SomeHorrendousException {
if (checkSomeObjectState()) {
return new ObjectOfSomeType();
}
try {
// yada yada yada...
} catch (SomeHorrendousException shexc) {
// wow, do something about this horrendous exception...
} finally {
// do some really important cleanup and state invalidation stuff...
}
Sé que ninguno de ustedes haría esto, así que dudé en agregar esto como un posible escenario, pero pensé, eh, es viernes, qué diablos; )
Probando el bloque finally en diferente declaración en el bloque try.
public static void main(String [] args){
try{
System.out.println("Before Statement");
/*** Statement ***/
System.out.println("After Statement");
}
catch(Exception e){
}
finally{
System.out.println("Finally is Executed");
}
Las declaraciones en las que finalmente se ejecuta el bloque son las siguientes:
-
Thread.currentThread().interrupted();
-
Thread.currentThread().destroy();
-
Thread.currentThread().stop();
-
Thread.sleep(10);
-
Thread.currentThread().interrupt();
-
Runtime.getRuntime().addShutdownHook(Thread.currentThread());
- Si hay alguna excepción ocurrida.
- Si no hay excepción.
Las declaraciones en las que finalmente no se ejecuta el bloque son las siguientes:
-
Thread.currentThread().suspend();
-
System.exit(0);
- JVM se estrelló.
- Se apaga el chip de la CPU.
- El sistema operativo mata el proceso JVM.
-
Runtime.getRuntime().exit(0);
-
Runtime.getRuntime().halt(0);
Puedes hacerlo parte de Daemon Thread. Puede usar el método setDaemon(boolean status)
que se usa para marcar el hilo actual como hilo de demonio o hilo de usuario y salir de la JVM cuando sea necesario. Esto le permitirá salir de la JVM antes de que finally{}
se ejecute finally{}
.
Si llama a System.exit()
el programa sale inmediatamente sin que finally
haya llamado.
Un fallo de JVM, por ejemplo, falla de segmentación, también evitará que finalmente se llame. es decir, la JVM se detiene inmediatamente en este punto y produce un informe de fallo.
Un bucle infinito también evitaría que finalmente se llamara.
El bloque final siempre se llama cuando se lanza un Throwable. Incluso si llamas a Thread.stop (), lo que hace que se ThreadDeath
un ThreadDeath
en el hilo de destino. Esto puede ser atrapado (es un Error
) y se llamará el bloque finally.
public static void main(String[] args) {
testOutOfMemoryError();
testThreadInterrupted();
testThreadStop();
test();
}
private static void testThreadStop() {
try {
try {
final Thread thread = Thread.currentThread();
new Thread(new Runnable() {
@Override
public void run() {
thread.stop();
}
}).start();
while(true)
Thread.sleep(1000);
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void testThreadInterrupted() {
try {
try {
final Thread thread = Thread.currentThread();
new Thread(new Runnable() {
@Override
public void run() {
thread.interrupt();
}
}).start();
while(true)
Thread.sleep(1000);
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void testOutOfMemoryError() {
try {
try {
List<byte[]> bytes = new ArrayList<byte[]>();
while(true)
bytes.add(new byte[8*1024*1024]);
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void test() {
try {
try {
test0();
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void test0() {
test0();
}
huellas dactilares
finally called after java.lang.OutOfMemoryError: Java heap space
finally called after java.lang.InterruptedException: sleep interrupted
finally called after java.lang.ThreadDeath
finally called after java.lang.Error
Nota: en cada caso, el hilo siguió funcionando, incluso después de SO, OOME, Interrupted and Thread.stop ()!
Uno podría ser "A finalmente es una parte del hilo de daeomon que puede no ejecutarse".