Nota: Si la JVM se cierra mientras se está ejecutando el código try o catch, es posible que el bloque finalmente no se ejecute. Asimismo, si el hilo que ejecuta el código try o catch se interrumpe o se mata, es posible que el bloque finalmente no se ejecute aunque la aplicación en su conjunto continúe.
No conozco otras formas en que el bloque finalmente no se ejecute ...
@dhiller - Estoy bastante seguro de que "apagar" está incluido en "Si la JVM sale ..." :-p
Jason Coco
2
@Jason Coco: Terminar (como en caso de pérdida de energía) no es lo mismo que salir; el segundo es un proceso más o menos organizado que culmina en el primero. ; p
user359996
2
AFAIK, si se interrumpe un hilo, no se detiene inmediatamente. Depende del código en el hilo detectar la interrupción y detener su tarea, por lo que finalmente el código debería ejecutarse.
Bart van Heukelom
2
Supongo que si se lanza una excepción en el bloque finalmente, el resto del bloque no se ejecuta.
Termina la máquina virtual Java en ejecución. El argumento sirve como código de estado; por convención, un código de estado distinto de cero indica una terminación anormal.
Este método llama al exitmétodo en clase Runtime. Este método nunca regresa normalmente.
Además, una excepción debería apagar la máquina virtual Java.
kaissun
3
Si ocurre una excepción mientras se ejecuta System.exit (0), finalmente se ejecutará el bloque.
Halil el
50
Solo para ampliar lo que otros han dicho, cualquier cosa que no cause algo como la salida de JVM incurrirá en el bloqueo final. Entonces el siguiente método:
esto realmente me confundió por un par de horas hace unas semanas.
nickf
3
Se considera una mala idea devolver un valor de un bloque finalmente. Regrese solo desde el bloque try o regrese desde fuera del bloque try /. La mayoría de los IDE marcarán esto con una advertencia.
Ran Biron
1
@nickf Supongo que ya no estás confundido. ¿Podría explicar la mecánica de por qué se devuelve 1 y no 0? Solo puedo adivinar que la memoria (o es un registro) que almacena el valor de retorno de la función que inicialmente contiene 0, se sobrescribe cuando se ejecuta el bloque finalmente .
Yaneeve
2
Eso es curioso, en C # no se permite regresar de un bloque finalmente.
JMCF125
3
@RanBiron Por supuesto. En realidad, no estaba recomendando regresar dentro de un bloque final, solo estaba tratando de demostrar que incluso una declaración de retorno aún hará que se ejecute el código en dicho bloque.
Aquarelle
15
En relación con System.exit, también hay ciertos tipos de fallas catastróficas en las que un bloque finalmente puede no ejecutarse. Si la JVM se queda sin memoria por completo, es posible que se cierre sin que se detecte o que finalmente suceda.
Específicamente, recuerdo un proyecto en el que intentamos tontamente usar
catch(OutOfMemoryError oome){// do stuff}
Esto no funcionó porque a la JVM no le quedaba memoria para ejecutar el bloque catch.
Cuando se lanza OutOfMemoryError, generalmente queda mucha memoria (para detener la agitación de GC). Sin embargo, si lo atrapa repetidamente, obviamente volverá a la goleada de GC.
Tom Hawtin - tackline
¡Pensé que no se deberían detectar excepciones no controladas!
Sergii Shevchyk
1
Lo intenté en mi lado, usando jdk7, ¡pero detectó el error OutOfMemory!
Jaskey
10
try{for(;;);}finally{System.err.println("?");}
En ese caso, el finalmente no se ejecutará (a menos que Thread.stopse llame al obsoleto , o un equivalente, digamos, a través de una interfaz de herramientas).
No creo que haya trampa. Quizás ahí te estás imaginando una trampa que no está ahí. Si ponemos un explícito throw, entonces el finallybloque se ejecutará como se esperaba. try { throw new ThreadDeath(); } finally { System.err.println("?"); }
Tom Hawtin - tackline
9
El tutorial de Sun se ha citado incorrectamente aquí en este hilo.
Nota: Si las salidas de JVM mientras se está ejecutando el código try o catch, el bloque finally se ha ejecutado. Del mismo modo, si el hilo de ejecutar el código try o captura se interrumpe o se mató, el bloque finally se no se ejecutará aunque la aplicación en su conjunto sigue.
Si observa detenidamente el tutorial de Sun para finalmente bloquear, no dice "no se ejecutará" pero "puede que no se ejecute" Aquí está la descripción correcta
Nota: Si las salidas de JVM mientras se está ejecutando el código try o catch, el bloque finally pueden no ejecutarse. Del mismo modo, si el hilo de ejecutar el código try o captura se interrumpe o se mató, el bloque finally puede no ejecutarse aunque la aplicación en su conjunto sigue.
La razón aparente de este comportamiento es que la llamada a system.exit () se procesa en un subproceso del sistema en tiempo de ejecución que puede tardar un tiempo en cerrar el jvm, mientras que el programador del subproceso puede solicitar finalmente que se ejecute. Finalmente, está diseñado para ejecutarse siempre, pero si está cerrando jvm, puede suceder que jvm se apague antes de que finalmente se ejecute.
Técnicamente, el bloque try nunca sale, por lo que el bloque finalmente nunca debería tener la oportunidad de ejecutarse. Lo mismo podría decirse de un bucle infinito.
Jeff Mercado
6
Si la JVM se cierra mientras se está ejecutando el código try o catch, es posible que el bloque finalmente no se ejecute. ( fuente )
Apagado normal: esto ocurre cuando el último hilo que no es un demonio sale O cuando Runtime.exit () ( fuente )
Cuando un subproceso sale, la JVM realiza un inventario de los subprocesos en ejecución, y si los únicos subprocesos que quedan son subprocesos de demonio, inicia un cierre ordenado. Cuando la JVM se detiene, todos los subprocesos de demonio restantes se abandonan, finalmente los bloques no se ejecutan, las pilas no se desenrollan y la JVM simplemente sale. Los subprocesos de daemon deben usarse con moderación, pocas actividades de procesamiento pueden abandonarse de manera segura en cualquier momento sin limpieza. En particular, es peligroso utilizar subprocesos de demonio para tareas que podrían realizar cualquier tipo de E / S. Los subprocesos de Daemon se guardan mejor para tareas de "limpieza", como un subproceso en segundo plano que elimina periódicamente las entradas caducadas de un caché en memoria. ( fuente )
Ejemplo de salida del último hilo no demonio:
publicclassTestDaemon{privatestaticRunnable runnable =newRunnable(){@Overridepublicvoid run(){try{while(true){System.out.println("Is alive");Thread.sleep(10);// throw new RuntimeException();}}catch(Throwable t){
t.printStackTrace();}finally{System.out.println("This will never be executed.");}}};publicstaticvoid main(String[] args)throwsInterruptedException{Thread daemon =newThread(runnable);
daemon.setDaemon(true);
daemon.start();Thread.sleep(100);// daemon.stop();System.out.println("Last non-daemon thread exits.");}}
Salida:
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.Is alive
Is alive
Is alive
Is alive
Is alive
Hay dos formas de detener finalmente la ejecución del código de bloqueo:
1. Utilice System.exit ();
2. Si de alguna manera el control de ejecución no llega a intentar bloquear.
Ver:
publicclassMain{publicstaticvoid main (String[]args){if(true){System.out.println("will exceute");}else{try{System.out.println("result = "+5/0);}catch(ArithmeticException e){System.out.println("will not exceute");}finally{System.out.println("will not exceute");}}}}
Me he encontrado con un caso muy específico del bloque finalmente que no se ejecuta relacionado específicamente con el marco de juego.
Me sorprendió descubrir que el bloque finalmente en este código de acción del controlador solo se llamó después de una excepción, pero nunca cuando la llamada realmente tuvo éxito.
try{InputStream is = getInputStreamMethod();
renderBinary(is,"out.zip");catch(Exception e){
e.printStackTrace();}finally{
cleanUp();}
Quizás el hilo se termina o algo cuando se llama a renderBinary (). Sospecho que sucede lo mismo con otras llamadas a render (), pero no lo verifiqué.
Resolví el problema moviendo renderBinary () después de try / catch. Una investigación adicional reveló que play proporciona una anotación @Finally para crear un método que se ejecuta después de que se ejecuta una acción del controlador. La advertencia aquí es que se llamará después de la ejecución de CUALQUIER acción en el controlador, por lo que puede que no siempre sea una buena opción.
//If ArithmeticException Occur Inner finally would not be executedclassTemp{publicstaticvoid main(String[] s){try{int x =10/s.length;System.out.println(x);try{int z[]=newint[s.length];
z[10]=1000;}catch(ArrayIndexOutOfBoundsException e){System.out.println(e);}finally{System.out.println("Inner finally");}}catch(ArithmeticException e){System.out.println(e);}finally{System.out.println("Outer Finally");}System.out.println("Remaining Code");}}
Respuestas:
de los tutoriales del sol
No conozco otras formas en que el bloque finalmente no se ejecute ...
fuente
System.exit apaga la máquina virtual.
"bye" no se imprime en el código anterior.
fuente
Solo para ampliar lo que otros han dicho, cualquier cosa que no cause algo como la salida de JVM incurrirá en el bloqueo final. Entonces el siguiente método:
extrañamente compilará y devolverá 1.
fuente
En relación con System.exit, también hay ciertos tipos de fallas catastróficas en las que un bloque finalmente puede no ejecutarse. Si la JVM se queda sin memoria por completo, es posible que se cierre sin que se detecte o que finalmente suceda.
Específicamente, recuerdo un proyecto en el que intentamos tontamente usar
Esto no funcionó porque a la JVM no le quedaba memoria para ejecutar el bloque catch.
fuente
En ese caso, el finalmente no se ejecutará (a menos que
Thread.stop
se llame al obsoleto , o un equivalente, digamos, a través de una interfaz de herramientas).fuente
throw
, entonces elfinally
bloque se ejecutará como se esperaba.try { throw new ThreadDeath(); } finally { System.err.println("?"); }
El tutorial de Sun se ha citado incorrectamente aquí en este hilo.
Nota: Si las salidas de JVM mientras se está ejecutando el código try o catch, el bloque finally se ha ejecutado. Del mismo modo, si el hilo de ejecutar el código try o captura se interrumpe o se mató, el bloque finally se no se ejecutará aunque la aplicación en su conjunto sigue.
Si observa detenidamente el tutorial de Sun para finalmente bloquear, no dice "no se ejecutará" pero "puede que no se ejecute" Aquí está la descripción correcta
La razón aparente de este comportamiento es que la llamada a system.exit () se procesa en un subproceso del sistema en tiempo de ejecución que puede tardar un tiempo en cerrar el jvm, mientras que el programador del subproceso puede solicitar finalmente que se ejecute. Finalmente, está diseñado para ejecutarse siempre, pero si está cerrando jvm, puede suceder que jvm se apague antes de que finalmente se ejecute.
fuente
Además, si ocurre un interbloqueo / bloqueo activo dentro del
try
bloque.Aquí está el código que lo demuestra:
Este código produce la siguiente salida:
y "finalmente" nunca se imprime
fuente
Si la JVM se cierra mientras se está ejecutando el código try o catch, es posible que el bloque finalmente no se ejecute. ( fuente )
Apagado normal: esto ocurre cuando el último hilo que no es un demonio sale O cuando Runtime.exit () ( fuente )
Cuando un subproceso sale, la JVM realiza un inventario de los subprocesos en ejecución, y si los únicos subprocesos que quedan son subprocesos de demonio, inicia un cierre ordenado. Cuando la JVM se detiene, todos los subprocesos de demonio restantes se abandonan, finalmente los bloques no se ejecutan, las pilas no se desenrollan y la JVM simplemente sale. Los subprocesos de daemon deben usarse con moderación, pocas actividades de procesamiento pueden abandonarse de manera segura en cualquier momento sin limpieza. En particular, es peligroso utilizar subprocesos de demonio para tareas que podrían realizar cualquier tipo de E / S. Los subprocesos de Daemon se guardan mejor para tareas de "limpieza", como un subproceso en segundo plano que elimina periódicamente las entradas caducadas de un caché en memoria. ( fuente )
Ejemplo de salida del último hilo no demonio:
Salida:
fuente
En los siguientes casos, el bloque finalmente no se ejecutará: -
System.exit(0)
se invoca desdetry
block.try
bloqueTambién puede haber otros casos marginales, donde finalmente no se ejecutará el bloqueo.
fuente
Hay dos formas de detener finalmente la ejecución del código de bloqueo:
1. Utilice System.exit ();
2. Si de alguna manera el control de ejecución no llega a intentar bloquear.
Ver:
fuente
Me he encontrado con un caso muy específico del bloque finalmente que no se ejecuta relacionado específicamente con el marco de juego.
Me sorprendió descubrir que el bloque finalmente en este código de acción del controlador solo se llamó después de una excepción, pero nunca cuando la llamada realmente tuvo éxito.
Quizás el hilo se termina o algo cuando se llama a renderBinary (). Sospecho que sucede lo mismo con otras llamadas a render (), pero no lo verifiqué.
Resolví el problema moviendo renderBinary () después de try / catch. Una investigación adicional reveló que play proporciona una anotación @Finally para crear un método que se ejecuta después de que se ejecuta una acción del controlador. La advertencia aquí es que se llamará después de la ejecución de CUALQUIER acción en el controlador, por lo que puede que no siempre sea una buena opción.
fuente
fuente