A palavra -chave finalmente em Java é geralmente usada com o bloco de tentativa de captura. Usado para executar algumas operações de liberação de recursos antes do final do método ou quando ocorre uma exceção. Recentemente, também vi alguns artigos na Internet discutindo a ordem da execução de tentar capturar as palavras -chave finalmente, e é dado que o bloco finalmente é executado no final do método.
Essas visões geralmente acreditam que:
1) A palavra -chave finalmente é executada antes de retornar ao método anterior após a instrução Retorno do programa. O valor de retorno será salvo em uma área temporária. Após a execução do bloco final, o valor da área temporária será retornado.
2) Se houver um valor de retorno no bloco Finalmente, ele substituirá o valor armazenado na área temporária do bloco de tentativa ou captura anterior no programa.
Mas o problema é realmente assim? Vamos pensar sobre isso com cuidado. A JVM explica e executa as instruções de bytecode no tempo de execução. Quando ele executa a declaração de retorno, ele não sabe se há um bloco finalmente depois? E se não houver finalmente bloco? Seja uma instrução de bytecode ou uma instrução de computador deve ser clara. A JVM não é tão inteligente. A mesma instrução deve ser clara e não conter dois significados. Portanto, não importa qual seja a declaração de devolução ao executar, o conteúdo da pilha será exibido e retornado ao método de chamada.
Ao mesmo tempo, podemos ver que o livro "profundamente em Java Virtual Machine" dá outra explicação. Quando o compilador Java compila a cláusula finalmente, uma instrução JSR será gerada. Isso faz com que a JVM seja chamada para uma mini sub -rotina para execução, ou seja, no bloco finalmente. Ao mesmo tempo, a instrução Return 0 no programa é compilada na variável de retorno na pilha para a variável local antes de ligar para a instrução JSR, e a instrução JSR é chamada, o bloco finalmente é executado e o bloco finalmente retorna. Quando o valor de retorno na variável local é empurrado para a pilha, a instrução do IreTurn é executada, o valor de retorno aparece da pilha e retorna ao método de chamada. Aqui, o valor de retorno é salvo na variável local antes de executar a instrução JSR, porque pode ocorrer uma exceção durante a execução do bloco finalmente ou também há valores de retorno. Somente dessa maneira a consistência da execução final do programa pode ser garantida. Desde que a "Máquina Virtual Java" aprofundada "foi escrita há algum tempo, a implementação e a versão do compilador JVM usadas pelo autor também são diferentes das discutidas neste artigo. Portanto, após o teste, há uma pequena diferença na geração de bytecodes para diferentes implementações do compilador ou versões de diferentes compiladores para o mesmo programa. Se você estiver interessado, pode dar uma olhada no bytecode gerado pela cláusula finalmente neste livro.
A geração de bytecode neste artigo é compilada e gerada pela versão JDK8U-25 do Oracle do compilador.
Vamos dar uma olhada em um exemplo abaixo.
1.Try Catch finalmente exemplo:
public class Finalmente, o Void estático de estático (string [] args) {int r = test (); System.out.println (r); } public static int test () {try {System.out.println ("Try"); // retorna 1/0; retornar 0; } catch (Exceção e) {System.out.println ("Exception"); retornar 100; } finalmente {System.out.println ("finalmente"); }}}Use a instrução Return 0 no bloco de tentativa, e o resultado em execução do programa é:
tentar
Finalmente
0
Use a declaração de retorno 1/0 no bloco de tentativa, e o resultado do programa em execução é:
Exceção
Finalmente
100
De fato, através do resultado em execução, podemos ver que o bloco finalmente é executado após outras instruções antes da declaração de retorno no bloco de tentativa ou captura. Em outras palavras, a ordem de escrita do programa não corresponde à nossa ordem de execução, porque a JVM interpreta e executa o ByteCode, por isso precisamos ver como o compilador Java compila esse código e ver como é o gerado pelo bytecode.
2. Parte do bytecode gerado pelo programa: (Consulte a instrução Java ByteCode)
public static int test (); Descritor: () I Sinalizadores: Acc_public, Acc_static Code: Stack = 2, habitantes locais = 2, args_size = 0 0: getStatic #20 // campo java/lang/system.out: ljava/io/printStream; 3: LDC #36 // String Try 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 // String 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/ljAut: ljava 19: getstatic #20 // campo java/lang/ljavin: ljava 19: getstatic #20 // field java/lang/system.out: 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 // String finally 32: invokevirtual #38 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 35: bipush 100 37: ireturn 38: store_1 39: getstatic #20 // Field java/lang/System.out:Ljava/io/PrintStream; 42: LDC #41 // String Finalmente 44: InvokeVirtual #38 // Método java/io/printStream.println: (ljava/lang/string;) v 47: aload_1 48: ATHOW Exception Tabela: De Tipo Tipo 0 8 18 Classe Java/Lang/Lang/Exceção 08 78 78: qualquer
A partir da parte vermelha, podemos ver que as linhas 10 e 11 correspondem a finalmente bloquear as instruções da instrução, 16 e 17 correspondem às instruções de retornar 0, após outras declarações no bloco de tentativa, antes de retornar. 19 e 20 correspondem a finalmente bloquear as instruções, 21 e 22 correspondem às instruções das declarações de retorno 100. Depois de pegar outras declarações e antes de retornar, podemos ver que tudo acontece por trás disso é que o compilador Java fez tudo isso por nós. Quanto às exceções que ocorrem no programa, a JVM encontrará o local do endereço correspondente para lidar com exceções da tabela de exceção para executar.
Portanto, podemos concluir que as declarações nos blocos finalmente serão inseridas pelo compilador Java antes do bloco de tentativa e do bloqueio de captura, e após as outras declarações. Não há sub -rotinas para gerar chamadas de JSR aqui. É por isso que, seja executando o bloco de tentativa ou executando o bloco de captura, o bloco finalmente será executado antes que o método retorne.
A análise abrangente acima do tempo de execução do Java Finalmente blocos é todo o conteúdo que compartilho com você. Espero que você possa lhe dar uma referência e espero que você possa apoiar mais o wulin.com.