Le mot-clé enfin en Java est généralement utilisé avec le bloc Try Catch. Utilisé pour effectuer certaines opérations de libération de ressources avant la fin de la méthode ou lorsqu'une exception se produit. Récemment, j'ai également vu des articles sur Internet en discutant de l'ordre de l'exécution de Try Catch Enfin les mots clés, et il est donné que le bloc final est exécuté à la fin de la méthode.
Ces opinions croient généralement que:
1) Le mot-clé final est exécuté avant de revenir à la méthode précédente après l'instruction Retour du programme. La valeur de retour sera enregistrée dans une zone temporaire. Une fois le bloc final exécuté, la valeur de la zone temporaire sera renvoyée.
2) S'il y a une valeur de retour dans le bloc enfin, il remplacera la valeur stockée dans la zone temporaire du bloc d'essai ou de capture précédent dans le programme.
Mais le problème est-il vraiment comme ça? Réfléchissons attentivement. JVM explique et exécute les instructions ByteCode au moment de l'exécution. Lorsqu'il exécute l'instruction RETOUR, il ne sait pas s'il y a un bloc finalement par la suite? Et s'il n'y a pas enfin de bloc? Qu'il s'agisse d'une instruction bytecode ou d'une instruction informatique doit être claire. JVM n'est pas si intelligent. La même instruction doit être claire et ne contiendra pas deux significations. Par conséquent, quelle que soit l'instruction de retour lors de l'exécution, le contenu de la pile sera apparu et retourné à la méthode d'appel.
En même temps, nous pouvons voir que le livre "Deep Into Java Virtual Machine" donne une autre explication. Lorsque le compilateur Java compile la clause Finalement, une instruction JSR sera générée. Il provoque l'appel de la JVM à un mini sous-programme pour l'exécution, c'est-à-dire au bloc final. Dans le même temps, l'instruction RETOUR 0 dans le programme est compilée dans la variable de retour dans la pile à la variable locale avant d'appeler l'instruction JSR, et l'instruction JSR est appelée, le bloc final est exécuté et le bloc finalement renvoie. Lorsque la valeur de retour dans la variable locale est poussée dans la pile, l'instruction Ireturn est exécutée, la valeur de retour apparaît à partir de la pile et revient à la méthode d'appel. Ici, la valeur de retour est enregistrée dans la variable locale avant d'exécuter l'instruction JSR, car une exception peut se produire lors de l'exécution du bloc enfin ou il y a également des valeurs de retour. Ce n'est que de cette manière que la cohérence de l'exécution du programme final peut être assurée. Étant donné que "l'approfondissement de la machine virtuelle Java" est écrite depuis un certain temps, l'implémentation et la version du compilateur JVM utilisées par l'auteur sont également différentes de celle discutée dans cet article. Ainsi, après les tests, il y a une légère différence dans la génération de codes occulés pour différentes implémentations de compilateurs ou versions de différents compilateurs pour le même programme. Si vous êtes intéressé, vous pouvez jeter un œil au bytecode généré par la clause enfin de ce livre.
La génération de bytecode dans cet article est compilée et générée par la version JDK8U-25 d'Oracle du compilateur.
Jetons un coup d'œil à un exemple ci-dessous.
1. Try Catch Exemple:
classe publique enfinTest {public static void main (String [] args) {int r = test (); System.out.println (R); } public static int test () {try {System.out.println ("try"); // Retour 1/0; retour 0; } catch (exception e) {System.out.println ("Exception"); retour 100; } enfin {System.out.println ("enfin"); }}}Utilisez l'instruction Return 0 dans le bloc d'essai, et le résultat en cours d'exécution du programme est:
essayer
Enfin
0
Utilisez l'instruction RETOUR 1/0 dans le bloc d'essai, et le résultat de l'exécution du programme est:
Exception
Enfin
100
En fait, grâce au résultat en cours d'exécution, nous pouvons voir que le bloc final est exécuté après d'autres instructions avant l'instruction de retour dans le bloc d'essai ou de capture. En d'autres termes, l'ordre d'écriture du programme ne correspond pas à notre ordre d'exécution, car JVM interprète et exécute ByteCode, nous devons donc voir à quoi ressemble le compilateur Java compile ce code et voir à quoi ressemble le bytecode.
2. Partie du bytecode généré par le programme: (Veuillez vous référer à l'instruction Java Bytecode)
Public Static int test (); Descriptor: () I Flags: ACC_PUBLIC, ACC_STATIC CODE: Stack = 2, Locals = 2, Args_Size = 0 0: GetStatic # 20 // Field Java / Lang / System.out: Ljava / Io / PrintStream; 3: LDC # 36 // String Try 5: invokeVirtual # 38 // Méthode java / io / printstream.println: (ljava / lang / string;) v 8: getStatic # 20 // field java / lang / system.out: ljava / io / printstream; 11: LDC # 41 // String enfin 13: invokevirtual # 38 // Méthode java / io / printstream.println: (ljava / lang / string;) v 16: iconst_0 17: ireturn 18: store_0 19: getStatic # 20 // champ java / lang / system.out: ljava / io / printStream; 22: LDC # 43 // Exception de chaîne 24: invokevirtual # 38 // Méthode java / io / printstream.println: (ljava / lang / string;) v 27: getStatic # 20 // champ java / lang / system.out: ljava / io / printstream; 30: LDC # 41 // String enfin 32: invokeVirtual # 38 // Méthode 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 / imprimstream; 42: LDC # 41 // String enfin 44: invokevirtual # 38 // Méthode java / io / printStream.println: (ljava / lang / string;) v 47: aload_1 48: Athrow Exception Table
D'après la partie rouge, nous pouvons voir que les lignes 10 et 11 correspondent aux instructions de l'instruction de blocage enfin, 16 et 17 correspondent aux instructions de retour 0, après d'autres instructions sur le bloc d'essai, avant de retourner. 19 et 20 correspondent à des instructions finalement en blocs, 21 et 22 correspondent aux instructions des instructions de retour 100. Après avoir attrapé d'autres déclarations et avant de revenir, nous pouvons voir que tout se passe derrière ceux-ci est que le compilateur Java a fait tout cela pour nous. Quant aux exceptions qui se produisent dans le programme, JVM trouvera l'emplacement d'adresse correspondant pour gérer les exceptions de la table d'exception à exécuter.
Par conséquent, nous pouvons conclure que les instructions dans les blocs enfin seront insérées par le compilateur Java avant l'instruction RETOUR BLOC ET CATCH Block, et après les autres instructions. Il n'y a pas de sous-programmes pour générer des appels JSR ici. C'est pourquoi, qu'il s'agisse d'exécuter le bloc d'essai ou d'exécuter le bloc de capture, le bloc final sera exécuté avant le retour de la méthode.
L'analyse complète ci-dessus du calendrier d'exécution de Java Blocks est enfin tout le contenu que je partage avec vous. J'espère que vous pourrez vous faire référence et j'espère que vous pourrez soutenir Wulin.com plus.