2009-02-05 17 views
22

Soy un novato de Java y me preguntaba, si tengo el siguiente código Java típicaEn Java, ¿se garantiza que se llamará el bloque "finalmente" (en el método principal)?

public class MyApp { 
    public static void main(String[] args) { 
    try { 
     // do stuff 
    } catch { 
     // handle errors 
    } finally { 
     // clean up connections etc. 
    } 
    } 
} 

no la JVM garantía de que el bloque finally siempre se ejecute? Para entender de dónde vengo, estoy acostumbrado a los programas C/C++ que podrían colapsar si desreferencia un puntero NULL y no puede tener ningún código para ejecutar después de eso.

Pero como entiendo Java y el negocio de la memoria entera GC/logrado, en general, no hay tal cosa como una desreferencia de puntero nulo, todo es un expection capturable, por lo que no hay realmente una manera para que mi programa se bloquee que podría hacer se salta el final, o está allí? Por ejemplo, en Python, generalmente hago

try: 
    # do stuff 
except AnExceptionIKnewMightHappen: 
    # react in an appropriate way 
except: 
    # log that weird error I had not known could happen 

y nunca he tenido ninguna aplicación muerta sin pasar por mi código.

Por supuesto, si el sistema operativo por alguna razón mata el proceso (o si algo mata a todo el sistema, como desconectar el enchufe) no hay mucho que Java pueda hacer. Además, desde PHP conozco los errores no detectables contra los que no puedes protegerte, incluso si el intérprete todavía estaba allí después de que sucedió (al menos es capaz de emitir un mensaje adecuado).

Editar: Sólo por la claridad (no fue realmente mal entendido por cualquier persona), permítanme añadir que yo estaba buscando cosas dentro de mi código que podrían conducir a la que está siendo desviado por último. Así que apuntar a System.exit fue un recordatorio útil, aunque no puedo ver por qué me gustaría hacer algo así.

La salida de JVM es una forma bastante obvia y lo consideraría una causa externa. La nota que indica que también debes recordar la posibilidad de que los hilos salgan mientras la JVM y la aplicación siguen funcionando fue muy útil, porque aunque ahora también me parece obvio, no había pensado en ello.

+1

Gee, eso fue respuestas rápidas. Obviamente una pregunta muy novato. ¡Gracias de cualquier manera! –

+0

La respuesta es no, consulte los detalles aquí: http://tshikatshikaaa.blogspot.nl/2012/07/about-using-systemexit-in-try-catch.html – JVerstry

Respuesta

41

Básicamente sí, a excepción de la nota listed here (el énfasis es mío):

Si la JVM sale mientras que el código try o captura se está ejecutando, luego el bloque finalmente no puede ejecutar. Del mismo modo, si el subproceso que ejecuta el código try o catch se interrumpe o cancela, el bloque finally no se puede ejecutar aunque la aplicación como un todo continúe.

+15

Tenga en cuenta que tirar del cable de alimentación suele ser una buena manera de prevenir "finalmente" de ejecución, también ... –

+3

LOL - y si es una computadora portátil, las baterías de la computadora portátil mueren en el mismo momento: D –

+5

Dejar caer la computadora portátil de la historia principal de un raspador también evita ambos bloques finalmente * y * ¡ganchos de cierre! –

0

Erm, sí :) Ya sea que su código ingrese una captura o no, finalmente se ejecutará. Es un buen lugar para poner el código que se limpia después del intento.

Obviamente no se ejecutará si se rompe la JVM :)

0

Sí, el bloque finally siempre se ejecutará, a menos que se produzca un bloqueo de la JVM (muy raro, pero eso puede suceder).

12

no se garantiza:

public class Main { 
    public static void main(String args[]) { 
     try { 
      System.out.println("try"); 
      System.exit(0); 
     } catch (Exception e) { 
      System.out.println("exception"); 
     } finally { 
      System.out.println("finally"); 
     } 
    } 
} 

Run eso.

+0

No estoy seguro de cómo es relevante para "así que no hay realmente una manera de que mi programa se bloquee que podría hacer que omita finalmente, ¿o no?" Obviamente si sale de la JVM, powercycle la caja o disparar el monitor, finalmente, no se ejecutará.Sorprendido por los votos, pero quizás estoy celoso :) –

+0

Es una prueba simple por contraejemplo. Obviamente no está garantizado. Eso puede o no ser importante para usted. Y si ocurre con una salida "limpia", le garantizo que no es mejor en un bloqueo real. – cletus

+0

Creo que es seguro decir System.exit() es un caso especial –

8

En una palabra, sí.

código en el bloque finally en Java siempre se ejecuta a menos que:

  • La JVM sale durante el try o captura bloque
  • El hilo conductor del código se interrumpe o se mató durante el bloque try o captura

(a partir de: http://java.sun.com/docs/books/tutorial/essential/exceptions/finally.html)

Por lo tanto, a menos que llamar explícitamente System.exit (int), o matar el proceso o subproceso externamente, puedes confiar en eso.

3

Absolutamente, ese bloque finalmente se ejecutará, cada vez. Excepto en el caso de un bloqueo JVM o la llamada a la función exit(). He tenido código en el que la aplicación Java hacía llamadas al código nativo JNI que segfaulted. El bloqueo resultante mató a la JVM e impidió que finalmente se ejecutara.

2

Chris Cameron es correcto. Pero normalmente se ejecuta un finally -block. Nula dereferece puntero no existe en Java:

try { 
    List<Object> x = null; 
    x.get(1); //throws the unchecked NullPointerException 
} finally { 
    //will be executed 
} 

El fin-bloque es ejecutado.

+0

Eso es interesante, no lo sabía. Aunque todavía es bastante diferente de una segfault de C clásica. –

1

Sí, la JVM siempre lo ejecuta. Garantizado

Por supuesto ... si el JVM sí mismo muere (por ejemplo: System.exit()), entonces no está en condiciones de garantizar nada. Pero la muerte de JVM no es un problema dentro de Java.

+2

Esto no es correcto. ** Thread.stop() ** puede evitar ** finalmente ** bloques mientras la JVM sigue ejecutándose. –

0

las únicas excepciones en que finalmente no se ejecuta el bloque son, ya sea bloqueos JVM, o system.exit().

+0

Creo que finalmente se llaman bloques cuando se invoca 'System.exit()'. –

0

Parece bastante obvio que nada se ejecutará después de que JVM se cierre, o ejecutará el código en ese subproceso eliminado. Obvio. Por lo tanto, cuando se ejecuta JVM, se ejecutará cada código que se ejecutará, y después de salir de JVM o dentro de un hilo muerto, se ejecutará nada, incluso cualquier tipo de código. Entonces, no hay manera de prevenirlo, pero si hay una necesidad para la cláusula finally, ponlo.

Cuestiones relacionadas