La palabra clave finalmente en Java generalmente se usa con el bloque de captura de try. Se utiliza para realizar algunas operaciones de liberación de recursos antes del final del método o cuando se produce una excepción. Recientemente, también he visto algunos artículos en Internet discutiendo el orden de la ejecución de las palabras clave de la ejecución de try capt finalmente, y se da que el bloque finalmente se ejecuta al final del método.
Estos puntos de vista generalmente creen que:
1) La palabra clave finalmente se ejecuta antes de volver al método anterior después de la declaración de retorno del programa. El valor de retorno se guardará en un área temporal. Después de ejecutar el bloque final, se devolverá el valor del área temporal.
2) Si hay un valor de retorno en el bloque Finalmente, reemplazará el valor almacenado en el área temporal del bloque de tráfico o captura anterior en el programa.
¿Pero es el problema realmente así? Pensemos cuidadosamente en ello. JVM explica y ejecuta instrucciones de Bytecode en tiempo de ejecución. Cuando ejecuta la declaración de retorno, ¿no sabe si finalmente hay un bloque finalmente? ¿Qué pasa si no hay finalmente bloque? Si se trata de una instrucción ByTecode o una instrucción de computadora, debe ser clara. JVM no es tan inteligente. La misma instrucción debe ser clara y no contendrá dos significados. Por lo tanto, no importa cuál sea la declaración de devolución cuando se ejecute, el contenido de la pila se aparecerá y se devolverá al método de llamadas.
Al mismo tiempo, podemos ver que el libro "Profund en Java Virtual Machine" da otra explicación. Cuando el compilador Java compila la cláusula Finalmente, se generará una instrucción JSR. Hace que el JVM sea llamado a una mini subrutina para su ejecución, es decir, en el bloque finalmente. Al mismo tiempo, la declaración de retorno 0 en el programa se compila en la variable de retorno en la pila a la variable local antes de llamar a la instrucción JSR, y se llama la instrucción JSR, el bloque finalmente se ejecuta y el bloque de finalmente regresa. Cuando el valor de retorno en la variable local se empuja a la pila, se ejecuta la instrucción IRETURN, el valor de retorno aparece desde la pila y vuelve al método de llamada. Aquí, el valor de retorno se guarda en la variable local antes de ejecutar la instrucción JSR, porque puede ocurrir una excepción durante la ejecución del bloque Finalmente o también hay valores de devoluciones. Solo de esta manera se puede garantizar la consistencia de la ejecución final del programa. Dado que la "máquina virtual Java" se ha escrito durante algún tiempo, la implementación y la versión del compilador JVM utilizado por el autor también es diferente del discutido en este artículo. Entonces, después de las pruebas, hay una ligera diferencia en la generación de bytecodes para diferentes implementaciones de compiladores o versiones de diferentes compiladores para el mismo programa. Si está interesado, puede echar un vistazo al bytecode generado por la cláusula Finalmente en este libro.
La generación Bytecode en este artículo es compilada y generada por la versión JDK8U-25 de Oracle del compilador.
Echemos un vistazo a un ejemplo a continuación.
1.Tre la captura finalmente ejemplo:
clase pública Finalmente Test {public static void main (string [] args) {int r = test (); System.out.println (r); } public static int test () {try {system.out.println ("intent"); // devolver 1/0; regresar 0; } catch (Exception e) {System.out.println ("excepción"); regresar 100; } finalmente {System.out.println ("finalmente"); }}}Use la instrucción Return 0 en el bloque de prueba, y el resultado de ejecución del programa es:
intentar
Finalmente
0
Use la instrucción Return 1/0 en el bloque de prueba, y el resultado del programa en ejecución es:
Excepción
Finalmente
100
De hecho, a través del resultado de la ejecución, podemos ver que el bloque finalmente se ejecuta después de otras declaraciones antes de la declaración de devolución en el bloque de try o captación. En otras palabras, el orden de escritura del programa no coincide con nuestro orden de ejecución, porque JVM interpreta y ejecuta Bytecode, por lo que necesitamos ver cómo el compilador Java compila este código y ver cómo se ve el bytecode generado por el bytecode.
2. Parte del Bytecode generado por el programa: (consulte la instrucción de Bytecode de Java)
Public static int test (); Descriptor: () I Flags: ACC_Public, ACC_STAtic Code: stack = 2, locals = 2, args_size = 0 0: getstatic #20 // campo java/lang/system.out: ljava/io/printstream; 3: LDC #36 // String Prueba 5: InvokeVirtual #38 // Método java/io/printstream.println: (ljava/lang/string;) v 8: getstatic #20 // campo java/lang/system.out: ljava/io/printstream; 11: LDC #41 // cadena Finalmente 13: InvokeVirtual #38 // Método java/io/printstream.println: (ljava/lang/string;) v 16: iconst_0 17: ireturn 18: store_0 19: getstatic #20 // campo java/lang/system.out: ljava/io/printsteam; 22: LDC #43 // String Exception 24: InvokeVirtual #38 // Método java/io/printstream.println: (ljava/lang/string;) v 27: getstatic #20 // campo java/lang/system.out: ljava/io/printstream; 30: LDC #41 // cadena Finalmente 32: InvokeVirtual #38 // método java/io/printstream.println: (ljava/lang/string;) v 35: bipush 100 37: ireturn 38: store_1 39: getstatic #20 // campo java/lang/system.out: ljava/io/printstream; 42: LDC #41 // cadena Finalmente 44: InvokeVirtual #38 // método java/io/printstream.println: (lJava/lang/string;) v 47: Aload_1 48: Athrow Exception Tabla: Desde Tipo de destino 0 8 18 Java/Lang/Exception 0 8 38 Any 18 27 38 38
Desde la parte roja, podemos ver que las líneas 10 y 11 corresponden a las instrucciones de la declaración finalmente del bloque, 16 y 17 corresponden a las instrucciones de retorno 0, después de otras declaraciones en el bloque de try, antes de la devolución. 19 y 20 corresponden a las instrucciones finalmente de bloque, 21 y 22 corresponden a las instrucciones de declaraciones de devolución 100. Después de atrapar otras declaraciones y antes de regresar, podemos ver que todo sucede detrás de estas es que el compilador Java ha hecho todo esto por nosotros. En cuanto a las excepciones que ocurren en el programa, JVM encontrará la ubicación de la dirección correspondiente para manejar las excepciones de la tabla de excepciones para ejecutar.
Por lo tanto, podemos concluir que las declaraciones en bloques finalmente serán insertadas por el compilador Java antes de la declaración de retorno del bloque y el bloque de captura, y después de las otras declaraciones. No hay subrutinas para generar llamadas JSR aquí. Es por eso que, ya sea ejecutar el bloque de try o ejecutar el bloque de captura, el bloque finalmente se ejecutará antes de que el método regrese.
El análisis completo anterior del momento de ejecución de Java finalmente bloquea es todo el contenido que comparto con usted. Espero que pueda darle una referencia y espero que pueda apoyar más a Wulin.com.