Java _try{} ... catch{} ... finally{}
_ブロックでは、_finally{}
_内のコードは、try/catchで何が発生しても、実行が「保証されている」と一般に見なされています。しかし、 実行されない少なくとも2つの状況:
System.exit(0)
が呼び出された場合;または、printStackTrace()
で終了)_finally{}
_ブロックのコードの実行を妨げる他のプログラムの動作はありますか?コードはどの特定の条件下で実行されますか?
編集: NullUserExceptionが指摘したように、2番目のケースは実際には当てはまりません。標準エラーのテキストが標準出力で印刷され、上にスクロールしないとテキストが表示されないためだと思いました。 :)謝罪。
System.exit()
を呼び出すと、finally
が呼び出されずにプログラムが即座に終了します。
JVMクラッシュ(例:セグメンテーション違反は、最終的に呼び出されることも防ぎます。つまり、JVMはこの時点ですぐに停止し、クラッシュレポートを生成します。
無限ループも、finallyが呼び出されるのを防ぎます。
Throwableがスローされると、finallyブロックが常に呼び出されます。 ThreadDeath
をトリガーするThread.stop()を呼び出しても、ターゲットスレッドでスローされます。これはキャッチでき( Error
です)、finallyブロックが呼び出されます。
public static void main(String[] args) {
testOutOfMemoryError();
testThreadInterrupted();
testThreadStop();
testStackOverflow();
}
private static void testThreadStop() {
try {
try {
final Thread thread = Thread.currentThread();
new Thread(new Runnable() {
@Override
public void run() {
thread.stop();
}
}).start();
while(true)
Thread.sleep(1000);
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void testThreadInterrupted() {
try {
try {
final Thread thread = Thread.currentThread();
new Thread(new Runnable() {
@Override
public void run() {
thread.interrupt();
}
}).start();
while(true)
Thread.sleep(1000);
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void testOutOfMemoryError() {
try {
try {
List<byte[]> bytes = new ArrayList<byte[]>();
while(true)
bytes.add(new byte[8*1024*1024]);
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void testStackOverflow() {
try {
try {
testStackOverflow0();
} finally {
System.out.print("finally called after ");
}
} catch (Throwable t) {
System.out.println(t);
}
}
private static void testStackOverflow0() {
testStackOverflow0();
}
プリント
finally called after Java.lang.OutOfMemoryError: Java heap space
finally called after Java.lang.InterruptedException: sleep interrupted
finally called after Java.lang.ThreadDeath
finally called after Java.lang.StackOverflowError
注:いずれの場合も、SO、OOME、Interrupted、およびThread.stop()の後でも、スレッドは実行され続けます。
try
ブロックの無限ループ。
破損したRAM?プログラムは記述どおりに実行されなくなりましたか?私は実際にDOSマシンで一度デバッグしました。
最終的に呼び出されないのは次の場合のみです。
電源が切れた場合
最終的にそれ自体が例外をスローする(またはエラーになる)と、部分的に実行される可能性があります。
1つは、「最終的には実行されない可能性があるデーモンスレッドの一部です」のようになります。
Tryブロックの別のステートメントで最終的にブロックをテストします。
_ public static void main(String [] args){
try{
System.out.println("Before Statement");
/*** Statement ***/
System.out.println("After Statement");
}
catch(Exception e){
}
finally{
System.out.println("Finally is Executed");
}
_
最終的にブロックが実行されるであるステートメントは次のとおりです。
Thread.currentThread().interrupted();
Thread.currentThread().destroy();
Thread.currentThread().stop();
Thread.sleep(10);
Thread.currentThread().interrupt();
Runtime.getRuntime().addShutdownHook(Thread.currentThread());
最終的にブロックが実行されないのステートメントは次のとおりです。
Thread.currentThread().suspend();
System.exit(0);
Runtime.getRuntime().exit(0);
Runtime.getRuntime().halt(0);
なんらかの理由でJVMが突然終了した場合、それが原因で、コントロールがfinallyブロックに入らず、実行されないことが考えられます。
実行されなかったfinallyブロックのもう1つの可能性のあるインスタンスは、tryブロックに入る前にメソッドが返されるという設計が原因である可能性があります。
public ObjectOfSomeType getMeAnObjectOfSomeType() throws SomeHorrendousException {
if (checkSomeObjectState()) {
return new ObjectOfSomeType();
}
try {
// yada yada yada...
} catch (SomeHorrendousException shexc) {
// wow, do something about this horrendous exception...
} finally {
// do some really important cleanup and state invalidation stuff...
}
誰もこれをするつもりはないので、これを考えられるシナリオとして追加するのをためらっていましたが、ええと、金曜日です。 )
デーモンスレッドの一部にすることができます。現在のスレッドをデーモンスレッドまたはユーザースレッドとしてマークし、必要に応じてJVMを終了するために使用されるメソッドsetDaemon(boolean status)
を使用できます。これにより、finally{}
が実行される前にJVMを終了できます。