Y a-t-il une condition où finalement pourrait ne pas fonctionner en java? Merci.
Y a-t-il une condition où finalement pourrait ne pas fonctionner en java? Merci.
Réponses:
à partir des didacticiels Sun
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 ...
System.exit arrête la machine virtuelle.
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
exit
méthode en classeRuntime
. Cette méthode ne retourne jamais normalement.
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
"bye" ne s'imprime pas dans le code ci-dessus.
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:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
va étrangement compiler et retourner 1.
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.
try { for (;;); } finally { System.err.println("?"); }
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).
throw
, le finally
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".
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é.
Aussi si un blocage / blocage de la vie se produit à l'intérieur du try
bloc.
Voici le code qui le démontre:
public class DeadLocker {
private static class SampleRunnable implements Runnable {
private String threadId;
private Object lock1;
private Object lock2;
public SampleRunnable(String threadId, Object lock1, Object lock2) {
super();
this.threadId = threadId;
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
try {
synchronized (lock1) {
System.out.println(threadId + " inside lock1");
Thread.sleep(1000);
synchronized (lock2) {
System.out.println(threadId + " inside lock2");
}
}
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
}
public static void main(String[] args) throws Exception {
Object ob1 = new Object();
Object ob2 = new Object();
Thread t1 = new Thread(new SampleRunnable("t1", ob1, ob2));
Thread t2 = new Thread(new SampleRunnable("t2", ob2, ob1));
t1.start();
t2.start();
}
}
Ce code produit la sortie suivante:
t1 inside lock1
t2 inside lock1
et "enfin" n'est jamais imprimé
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:
public class TestDaemon {
private static Runnable runnable = new Runnable() {
@Override
public void 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.");
}
}
};
public static void main(String[] args) throws InterruptedException {
Thread daemon = new Thread(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
Dans les cas suivants, le bloc finally ne sera pas exécuté: -
System.exit(0)
est appelé à partir du try
bloc. try
blocage dans votre bloc Il peut également y avoir d'autres cas marginaux, où le bloc finally ne sera pas exécuté.
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:
public class Main
{
public static void 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 executed
class Temp
{
public static void main(String[] s)
{
try
{
int x = 10/s.length;
System.out.println(x);
try
{
int z[] = new int[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");
}
}