¿Existe alguna condición en la que finalmente no se pueda ejecutar en Java? Gracias.
¿Existe alguna condición en la que finalmente no se pueda ejecutar en Java? Gracias.
Respuestas:
de los tutoriales del sol
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 ...
System.exit apaga la máquina virtual.
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
exit
método en claseRuntime
. Este método nunca regresa normalmente.
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
"bye" no se imprime en el código anterior.
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:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
extrañamente compilará y devolverá 1.
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.
try { for (;;); } finally { System.err.println("?"); }
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).
throw
, entonces el finally
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
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.
Además, si ocurre un interbloqueo / bloqueo activo dentro del try
bloque.
Aquí está el código que lo demuestra:
public class DeadLocker {
private static class SampleRunnable implements Runnable {
private String threadId;
private Object lock1;
private Object lock2;
public SampleRunnable(String threadId, Object lock1, Object lock2) {
super();
this.threadId = threadId;
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
try {
synchronized (lock1) {
System.out.println(threadId + " inside lock1");
Thread.sleep(1000);
synchronized (lock2) {
System.out.println(threadId + " inside lock2");
}
}
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
}
public static void main(String[] args) throws Exception {
Object ob1 = new Object();
Object ob2 = new Object();
Thread t1 = new Thread(new SampleRunnable("t1", ob1, ob2));
Thread t2 = new Thread(new SampleRunnable("t2", ob2, ob1));
t1.start();
t2.start();
}
}
Este código produce la siguiente salida:
t1 inside lock1
t2 inside lock1
y "finalmente" nunca se imprime
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:
public class TestDaemon {
private static Runnable runnable = new Runnable() {
@Override
public void 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.");
}
}
};
public static void main(String[] args) throws InterruptedException {
Thread daemon = new Thread(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
En los siguientes casos, el bloque finalmente no se ejecutará: -
System.exit(0)
se invoca desde try
block. try
bloque También puede haber otros casos marginales, donde finalmente no se ejecutará el bloqueo.
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:
public class Main
{
public static void 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 executed
class Temp
{
public static void main(String[] s)
{
try
{
int x = 10/s.length;
System.out.println(x);
try
{
int z[] = new int[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");
}
}