Y a-t-il une condition où finalement pourrait ne pas fonctionner en java? Merci.
à partir du tutoriels 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 qui exécute le code try ou catch est interrompu ou tué, le bloc finally peut ne pas s'exécuter même si l'application continue dans son ensemble.
Je ne connais pas d'autre moyen d'empêcher le bloc final de s'exécuter ...
System.exit arrête la machine virtuelle.
Termine la machine virtuelle en cours d'exécution Java. 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 méthode
exit
de la 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'affiche pas dans le code ci-dessus.
Juste pour développer ce que d’autres ont dit, tout ce qui n’entraîne pas un événement similaire à celui de la sortie de la machine virtuelle Java entraîne le blocage du blocage. Donc, la méthode suivante:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
étrangement à la fois compiler et retourner 1.
En relation avec System.exit, il existe également certains types d'échec catastrophique dans lesquels un bloc finally peut ne pas s'exécuter. Si la machine virtuelle Java manque complètement de mémoire, il est possible qu'elle se ferme sans incident 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, la commande finally ne sera pas exécutée (à moins que le Thread.stop
est appelé, ou un équivalent, par exemple, via une interface d’outils).
Le tutoriel Sun a été cité à tort ici dans ce fil de discussion.
Remarque: Si la machine virtuelle Java se ferme pendant l'exécution du code try ou catch, le bloc finally sera ne sera pas exécuté. De même, si le thread qui exécute le code try ou catch est interrompu ou tué, le bloc finally sera ne sera pas exécuté même si l'application dans son ensemble continue.
Si vous examinez attentivement le tutoriel Sun pour finalement bloquer, il ne dit pas "n'exécutera pas" mais "ne pourra pas s'exécuter" Voici la description correcte
Remarque: Si la machine virtuelle Java se ferme pendant l'exécution du code try ou catch, le bloc finally peut ne s'exécute pas. De même, si le thread exécutant le code try ou catch est interrompu ou tué, le bloc finally peut ne s'exécute pas, 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 système d’exécution, ce qui peut prendre un certain temps pour arrêter jvm, tandis que le planificateur de thread peut demander à être exécuté. Donc, finalement, est conçu pour toujours être exécuté, mais si vous arrêtez jvm, il peut arriver que jvm s’arrête avant d’être enfin exécuté.
Aussi, si un blocage/livelock se produit dans le bloc try
.
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é
Voici quelques conditions qui peuvent contourner un blocage final:
Dernier exemple de 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.");
}
}
Sortie:
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 finalement de bloquer l'exécution du code:
1. Utilisez System.exit ();
2. Si, d'une manière ou d'une autre, le contrôle d'exécution ne parvient pas à 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");
}
}
}
}
Dans les cas suivants, finalement, le blocage ne sera pas exécuté: -
System.exit(0)
est appelé à partir du bloc try
.try
Il peut également y avoir d'autres cas marginaux, où le blocage final ne sera pas exécuté.
Je suis tombé sur un cas très spécifique de blocage du blocage final lié spécifiquement à la structure de jeu.
J'ai été surpris de constater que le dernier bloc de ce code d'action de contrôleur n'a été appelé qu'après une exception, mais jamais lorsque l'appel a abouti.
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 quand renderBinary () est appelé. Je soupçonne que la même chose se produit pour les autres appels de render (), mais je ne l'ai pas vérifiée.
J'ai résolu le problème en déplaçant la renderBinary () après le try/catch. Une enquête plus approfondie a révélé que play fournissait une annotation @Finally pour créer une méthode qui est exécutée après l'exécution d'une action du 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 peut-être pas toujours le bon choix.