Gibt es eine Bedingung, unter der möglicherweise nicht in Java ausgeführt wird? Vielen Dank.
Gibt es eine Bedingung, unter der möglicherweise nicht in Java ausgeführt wird? Vielen Dank.
Antworten:
aus den Sun Tutorials
Hinweis: Wenn die JVM beendet wird, während der Try- oder Catch-Code ausgeführt wird, wird der finally-Block möglicherweise nicht ausgeführt. Wenn der Thread, der den Try- oder Catch-Code ausführt, unterbrochen oder beendet wird, wird der finally-Block möglicherweise nicht ausgeführt, obwohl die gesamte Anwendung fortgesetzt wird.
Ich kenne keine anderen Möglichkeiten, wie der finally-Block nicht ausgeführt werden würde ...
System.exit fährt die virtuelle Maschine herunter.
Beendet die aktuell ausgeführte Java Virtual Machine. Das Argument dient als Statuscode. Gemäß der Konvention zeigt ein Statuscode ungleich Null eine abnormale Beendigung an.
Diese Methode ruft die
exit
Methode in der Klasse aufRuntime
. Diese Methode wird nie normal zurückgegeben.
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
"bye" wird im obigen Code nicht ausgedruckt.
Nur um das zu erweitern, was andere gesagt haben, wird alles, was nicht dazu führt, dass die JVM beendet wird, den endgültigen Block verursachen. Also die folgende Methode:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
wird seltsamerweise sowohl kompilieren als auch 1 zurückgeben.
Im Zusammenhang mit System.exit gibt es auch bestimmte Arten von katastrophalen Fehlern, bei denen ein finally-Block möglicherweise nicht ausgeführt wird. Wenn der JVM nicht genügend Speicherplatz zur Verfügung steht, wird sie möglicherweise einfach beendet, ohne dass sie abgefangen wird oder endgültig passiert.
Insbesondere erinnere ich mich an ein Projekt, bei dem wir dummerweise versucht haben, es zu verwenden
catch (OutOfMemoryError oome) {
// do stuff
}
Dies funktionierte nicht, da die JVM keinen Speicher mehr zum Ausführen des catch-Blocks hatte.
try { for (;;); } finally { System.err.println("?"); }
In diesem Fall wird die Funktion "finally" nicht ausgeführt (es sei denn, die veraltete Funktion Thread.stop
wird aufgerufen oder eine entsprechende Funktion, z. B. über eine Tool-Schnittstelle).
throw
, wird der finally
Block wie erwartet ausgeführt. try { throw new ThreadDeath(); } finally { System.err.println("?"); }
Das Sun-Tutorial wurde hier in diesem Thread falsch zitiert.
Hinweis: Wenn die JVM - Exits , während der Versuch oder Fang Code ausgeführt wird, dann wird der finally - Block wird nicht ausgeführt. Wenn der Thread, der den Try- oder Catch-Code ausführt, unterbrochen oder beendet wird, wird der finally-Block ebenfalls nicht ausgeführt, obwohl die gesamte Anwendung fortgesetzt wird.
Wenn Sie sich das Sun-Tutorial genau ansehen, um es endgültig zu blockieren, heißt es nicht "wird nicht ausgeführt", sondern "wird möglicherweise nicht ausgeführt". Hier ist die korrekte Beschreibung
Hinweis: Wenn die JVM beendet wird, während der Try- oder Catch-Code ausgeführt wird, wird der finally-Block möglicherweise nicht ausgeführt. Wenn der Thread, der den Try- oder Catch-Code ausführt, unterbrochen oder beendet wird, wird der finally-Block möglicherweise nicht ausgeführt, obwohl die gesamte Anwendung fortgesetzt wird.
Der offensichtliche Grund für dieses Verhalten ist, dass der Aufruf von system.exit () in einem Laufzeit-System-Thread verarbeitet wird, der einige Zeit zum Herunterfahren des JVM benötigen kann, während der Thread-Scheduler die endgültige Ausführung anfordern kann. Schließlich ist es so konzipiert, dass es immer ausgeführt wird. Wenn Sie jedoch jvm herunterfahren, kann es vorkommen, dass jvm heruntergefahren wird, bevor es endgültig ausgeführt wird.
Auch wenn ein Deadlock / Livelock innerhalb des try
Blocks auftritt .
Hier ist der Code, der dies demonstriert:
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();
}
}
Dieser Code erzeugt die folgende Ausgabe:
t1 inside lock1
t2 inside lock1
und "endlich" wird nie gedruckt
Wenn die JVM beendet wird, während der Try- oder Catch-Code ausgeführt wird, wird der finally-Block möglicherweise nicht ausgeführt. ( Quelle )
Normales Herunterfahren - Dies tritt entweder auf, wenn der letzte Nicht-Daemon-Thread beendet wird, oder wenn Runtime.exit () ( Quelle )
Wenn ein Thread beendet wird, führt die JVM eine Bestandsaufnahme der ausgeführten Threads durch. Wenn nur noch Daemon-Threads übrig sind, wird ein ordnungsgemäßes Herunterfahren eingeleitet. Wenn die JVM angehalten wird, werden alle verbleibenden Daemon-Threads abgebrochen und die Blöcke nicht ausgeführt. Die Stapel werden nicht abgewickelt. Die JVM wird gerade beendet. Daemon-Threads sollten sparsam verwendet werden. Nur wenige Verarbeitungsaktivitäten können jederzeit ohne Bereinigung sicher abgebrochen werden. Insbesondere ist es gefährlich, Daemon-Threads für Aufgaben zu verwenden, die möglicherweise E / A-Vorgänge ausführen. Daemon-Threads werden am besten für "Housekeeping" -Aufgaben gespeichert, z. B. für einen Hintergrund-Thread, der abgelaufene Einträge regelmäßig aus einem speicherinternen Cache entfernt. ( Quelle )
Der letzte Nicht-Daemon-Thread beendet das Beispiel:
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.");
}
}
Ausgabe:
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
In folgenden Fällen wird der endgültige Block nicht ausgeführt: -
System.exit(0)
wird vom try
Block aufgerufen . try
Block Es kann auch andere Randfälle geben, in denen der endgültige Block nicht ausgeführt wird.
Es gibt zwei Möglichkeiten, die Blockcodeausführung endgültig zu stoppen:
1. Verwenden Sie System.exit ();
2. Wenn die Ausführungskontrolle irgendwie nicht zum Blockieren reicht.
Sehen:
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");
}
}
}
}
Ich bin auf einen sehr speziellen Fall gestoßen, in dem der finally-Block nicht speziell im Zusammenhang mit dem Spiel-Framework ausgeführt wird.
Ich war überrascht, dass der finally-Block in diesem Controller-Aktionscode erst nach einer Ausnahme aufgerufen wurde, jedoch nie, wenn der Aufruf tatsächlich erfolgreich war.
try {
InputStream is = getInputStreamMethod();
renderBinary(is, "out.zip");
catch (Exception e) {
e.printStackTrace();
} finally {
cleanUp();
}
Möglicherweise wird der Thread beendet oder etwas, wenn renderBinary () aufgerufen wird. Ich würde vermuten, dass dasselbe bei anderen render () -Aufrufen passiert, aber ich habe es nicht überprüft.
Ich habe das Problem gelöst, indem ich renderBinary () nach dem try / catch nach verschoben habe. Weitere Untersuchungen ergaben, dass play eine @ Final-Annotation bereitstellt, um eine Methode zu erstellen, die ausgeführt wird, nachdem eine Controller-Aktion ausgeführt wurde. Die Einschränkung hierbei ist, dass dies nach der Ausführung einer beliebigen Aktion in der Steuerung aufgerufen wird, sodass dies möglicherweise nicht immer eine gute Wahl ist.
//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");
}
}