Remarque: si la machine virtuelle Java se ferme pendant l'exécution du code try ou catch, le bloc finally peut ne pas s'exécuter. De même, si le thread exécutant le code try ou catch est interrompu ou tué, le bloc finally peut ne pas s'exécuter même si l'application dans son ensemble continue.
Je ne connais aucune autre manière dont le bloc finally ne s'exécuterait pas ...
@dhiller - Je suis quasiment sûr que "power down" est inclus dans "If the JVM exits ..." :-p
Jason Coco
2
@Jason Coco: Mettre fin (comme en cas de perte d'alimentation) n'est pas tout à fait la même chose que de quitter; le second est un processus plus ou moins organisé aboutissant au premier. ; p
user359996
2
AFAIK, si un thread est interrompu, il n'est pas immédiatement arrêté. C'est au code dans le thread de détecter l'interruption et d'arrêter sa tâche, donc finalement le code doit s'exécuter.
Bart van Heukelom
2
Je suppose que si une exception est lancée dans le bloc finally, le reste du bloc n'est pas exécuté.
Met fin à la machine virtuelle Java en cours d'exécution. L'argument sert de code d'état; par convention, un code d'état différent de zéro indique une interruption anormale.
Cette méthode appelle la exitméthode en classe Runtime. Cette méthode ne retourne jamais normalement.
cela m'a vraiment dérouté pendant quelques bonnes heures il y a quelques semaines.
nickf le
3
Il est considéré comme une mauvaise idée de renvoyer une valeur à partir d'un bloc finally. Soit revenir uniquement du bloc try, soit revenir de l'extérieur du bloc try / finally. La plupart des IDE le marqueront avec un avertissement.
Ran Biron le
1
@nickf Je suppose que vous n'êtes plus confus. Pourriez-vous expliquer pourquoi 1 est retourné et non 0. Je ne pourrais que deviner que la mémoire (ou est-ce un registre) qui stocke la valeur de retour de la fonction qui contient initialement 0, est écrasée lorsque le bloc final est exécuté .
Yaneeve
2
C'est curieux, en C #, il n'est pas permis de revenir d'un bloc finally.
JMCF125
3
@RanBiron Bien sûr. Il ne recommandait pas réellement de revenir à l'intérieur d'un bloc finally, il essayait seulement de démontrer que même une instruction return provoquera toujours l'exécution du code dans ledit bloc.
Aquarelle
15
Lié à System.exit, il existe également certains types d'échec catastrophique où un bloc finally peut ne pas s'exécuter. Si la machine virtuelle Java est complètement à court de mémoire, elle peut simplement se fermer sans interruption ou finalement.
Plus précisément, je me souviens d'un projet où nous avons bêtement essayé d'utiliser
catch(OutOfMemoryError oome){// do stuff}
Cela n'a pas fonctionné car la machine virtuelle Java n'avait plus de mémoire pour exécuter le bloc catch.
Lorsque OutOfMemoryError est levé, il reste généralement beaucoup de mémoire (pour arrêter le battement GC). Cependant, si vous l'attrapez à plusieurs reprises, vous reviendrez évidemment à la raclée GC.
Tom Hawtin - tackline
Je pensais qu'il ne fallait pas attraper d'exceptions non contrôlées!
Sergii Shevchyk
1
J'ai essayé de mon côté, en utilisant jdk7, mais il a attrapé l'erreur OutOfMemory!
Jaskey
10
try{for(;;);}finally{System.err.println("?");}
Dans ce cas, le finally ne s'exécutera pas (à moins que le déprécié ne Thread.stopsoit appelé, ou un équivalent, par exemple, via une interface d'outils).
Je ne pense pas qu'il y ait un piège. Peut-être que là vous imaginez une prise qui n'est pas là. Si nous mettons un explicite throw, le finallybloc s'exécutera comme prévu. try { throw new ThreadDeath(); } finally { System.err.println("?"); }
Tom Hawtin - tackline
9
Le tutoriel Sun a été mal cité ici dans ce fil.
Remarque: si la machine virtuelle Java se ferme pendant l'exécution du code try ou catch, le bloc finally ne pas exécuter. De même, si le thread exécutant le code d'essai ou catch est interrompu ou tué, le bloc finally sera pas exécuté même si l'application dans son ensemble continue.
Si vous regardez de près le tutoriel de sun pour finalement bloquer, il ne dit pas "ne s'exécutera pas" mais "ne s'exécutera peut-être pas".
Remarque: si la machine virtuelle Java se ferme pendant l'exécution du code try ou catch, le bloc finally peut ne pas s'exécuter. De même, si le thread exécutant le code try ou catch est interrompu ou tué, le bloc finally peut ne pas s'exécuter même si l'application dans son ensemble continue.
La raison apparente de ce comportement est que l'appel à system.exit () est traité dans un thread du système d'exécution, ce qui peut prendre du temps pour arrêter le jvm, tandis que le planificateur de thread peut demander enfin à s'exécuter. Donc, finalement, est conçu pour toujours s'exécuter, mais si vous arrêtez jvm, il peut arriver que jvm s'arrête avant d'être finalement exécuté.
Techniquement, le bloc try ne se termine jamais, donc le bloc finally ne devrait jamais avoir une chance de s'exécuter. La même chose pourrait être dite pour une boucle infinie.
Jeff Mercado
6
Si la JVM se ferme pendant l'exécution du code try ou catch, le bloc finally peut ne pas s'exécuter. ( source )
Arrêt normal - cela se produit soit lorsque le dernier thread non démon se termine, soit lorsque Runtime.exit () ( source )
Lorsqu'un thread se termine, la JVM effectue un inventaire des threads en cours d'exécution, et si les seuls threads qui restent sont des threads démons, il lance un arrêt ordonné. Lorsque la JVM s'arrête, tous les threads de démon restants sont abandonnés, enfin les blocs ne sont pas exécutés, les piles ne sont pas déroulées, la JVM se ferme simplement. Les threads de démon doivent être utilisés avec parcimonie, peu d'activités de traitement peuvent être abandonnées en toute sécurité à tout moment sans nettoyage. En particulier, il est dangereux d'utiliser des threads de démon pour des tâches qui pourraient effectuer n'importe quel type d'E / S. Les threads de démon sont mieux enregistrés pour les tâches de «ménage», comme un thread d'arrière-plan qui supprime périodiquement les entrées expirées d'un cache en mémoire. ( source )
Exemple de sortie du dernier thread non démon:
publicclassTestDaemon{privatestaticRunnable runnable =newRunnable(){@Overridepublicvoid 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.");}}};publicstaticvoid main(String[] args)throwsInterruptedException{Thread daemon =newThread(runnable);
daemon.setDaemon(true);
daemon.start();Thread.sleep(100);// daemon.stop();System.out.println("Last non-daemon thread exits.");}}
Production:
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
Il y a deux façons d'arrêter enfin l'exécution du code de blocage:
1. Utilisez System.exit ();
2. Si en quelque sorte le contrôle d'exécution n'atteint pas pour essayer de bloquer.
Voir:
publicclassMain{publicstaticvoid 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");}}}}
Je suis tombé sur un cas très spécifique du bloc finally ne s'exécutant pas spécifiquement lié au cadre de jeu.
J'ai été surpris de constater que le bloc finally dans ce code d'action du contrôleur n'a été appelé qu'après une exception, mais jamais lorsque l'appel a réussi.
try{InputStream is = getInputStreamMethod();
renderBinary(is,"out.zip");catch(Exception e){
e.printStackTrace();}finally{
cleanUp();}
Peut-être que le thread est terminé ou quelque chose lorsque renderBinary () est appelé. Je soupçonnerais que la même chose se produit pour les autres appels render (), mais je ne l'ai pas vérifié.
J'ai résolu le problème en déplaçant le renderBinary () après le try / catch. Une enquête plus approfondie a révélé que play fournit une annotation @Finally pour créer une méthode qui est exécutée après l'exécution d'une action de contrôleur. La mise en garde ici est que cela sera appelé après l'exécution de N'IMPORTE QUELLE action dans le contrôleur, donc ce n'est pas toujours un bon choix.
//If ArithmeticException Occur Inner finally would not be executedclassTemp{publicstaticvoid main(String[] s){try{int x =10/s.length;System.out.println(x);try{int z[]=newint[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");}}
Réponses:
à partir des didacticiels Sun
Je ne connais aucune autre manière dont le bloc finally ne s'exécuterait pas ...
la source
System.exit arrête la machine virtuelle.
"bye" ne s'imprime pas dans le code ci-dessus.
la source
Juste pour développer ce que d'autres ont dit, tout ce qui ne provoque pas la sortie de la JVM entraînera le blocage final. Donc, la méthode suivante:
va étrangement compiler et retourner 1.
la source
Lié à System.exit, il existe également certains types d'échec catastrophique où un bloc finally peut ne pas s'exécuter. Si la machine virtuelle Java est complètement à court de mémoire, elle peut simplement se fermer sans interruption ou finalement.
Plus précisément, je me souviens d'un projet où nous avons bêtement essayé d'utiliser
Cela n'a pas fonctionné car la machine virtuelle Java n'avait plus de mémoire pour exécuter le bloc catch.
la source
Dans ce cas, le finally ne s'exécutera pas (à moins que le déprécié ne
Thread.stop
soit appelé, ou un équivalent, par exemple, via une interface d'outils).la source
throw
, lefinally
bloc s'exécutera comme prévu.try { throw new ThreadDeath(); } finally { System.err.println("?"); }
Le tutoriel Sun a été mal cité ici dans ce fil.
Remarque: si la machine virtuelle Java se ferme pendant l'exécution du code try ou catch, le bloc finally ne pas exécuter. De même, si le thread exécutant le code d'essai ou catch est interrompu ou tué, le bloc finally sera pas exécuté même si l'application dans son ensemble continue.
Si vous regardez de près le tutoriel de sun pour finalement bloquer, il ne dit pas "ne s'exécutera pas" mais "ne s'exécutera peut-être pas".
La raison apparente de ce comportement est que l'appel à system.exit () est traité dans un thread du système d'exécution, ce qui peut prendre du temps pour arrêter le jvm, tandis que le planificateur de thread peut demander enfin à s'exécuter. Donc, finalement, est conçu pour toujours s'exécuter, mais si vous arrêtez jvm, il peut arriver que jvm s'arrête avant d'être finalement exécuté.
la source
Aussi si un blocage / blocage de la vie se produit à l'intérieur du
try
bloc.Voici le code qui le démontre:
Ce code produit la sortie suivante:
et "enfin" n'est jamais imprimé
la source
Si la JVM se ferme pendant l'exécution du code try ou catch, le bloc finally peut ne pas s'exécuter. ( source )
Arrêt normal - cela se produit soit lorsque le dernier thread non démon se termine, soit lorsque Runtime.exit () ( source )
Lorsqu'un thread se termine, la JVM effectue un inventaire des threads en cours d'exécution, et si les seuls threads qui restent sont des threads démons, il lance un arrêt ordonné. Lorsque la JVM s'arrête, tous les threads de démon restants sont abandonnés, enfin les blocs ne sont pas exécutés, les piles ne sont pas déroulées, la JVM se ferme simplement. Les threads de démon doivent être utilisés avec parcimonie, peu d'activités de traitement peuvent être abandonnées en toute sécurité à tout moment sans nettoyage. En particulier, il est dangereux d'utiliser des threads de démon pour des tâches qui pourraient effectuer n'importe quel type d'E / S. Les threads de démon sont mieux enregistrés pour les tâches de «ménage», comme un thread d'arrière-plan qui supprime périodiquement les entrées expirées d'un cache en mémoire. ( source )
Exemple de sortie du dernier thread non démon:
Production:
la source
Dans les cas suivants, le bloc finally ne sera pas exécuté: -
System.exit(0)
est appelé à partir dutry
bloc.try
blocage dans votre blocIl peut également y avoir d'autres cas marginaux, où le bloc finally ne sera pas exécuté.
la source
Il y a deux façons d'arrêter enfin l'exécution du code de blocage:
1. Utilisez System.exit ();
2. Si en quelque sorte le contrôle d'exécution n'atteint pas pour essayer de bloquer.
Voir:
la source
Je suis tombé sur un cas très spécifique du bloc finally ne s'exécutant pas spécifiquement lié au cadre de jeu.
J'ai été surpris de constater que le bloc finally dans ce code d'action du contrôleur n'a été appelé qu'après une exception, mais jamais lorsque l'appel a réussi.
Peut-être que le thread est terminé ou quelque chose lorsque renderBinary () est appelé. Je soupçonnerais que la même chose se produit pour les autres appels render (), mais je ne l'ai pas vérifié.
J'ai résolu le problème en déplaçant le renderBinary () après le try / catch. Une enquête plus approfondie a révélé que play fournit une annotation @Finally pour créer une méthode qui est exécutée après l'exécution d'une action de contrôleur. La mise en garde ici est que cela sera appelé après l'exécution de N'IMPORTE QUELLE action dans le contrôleur, donc ce n'est pas toujours un bon choix.
la source
la source