最終的にJavaで実行されない可能性のある条件はありますか?ありがとう。
注:tryまたはcatchコードの実行中にJVMが終了すると、finallyブロックが実行されない場合があります。同様に、tryまたはcatchコードを実行しているスレッドが中断または強制終了された場合、アプリケーション全体が継続しても、finallyブロックは実行されない場合があります。
Finallyブロックが実行されない他の方法は知りません...
System.exit は、仮想マシンをシャットダウンします。
現在実行中のJava仮想マシン。引数はステータスコードとして機能します。慣例により、ゼロ以外のステータスコードは異常終了を示します。
このメソッドは、クラス
exit
のRuntime
メソッドを呼び出します。このメソッドは通常戻りません。
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
「bye」は上記のコードでは出力されません。
他の人が言ったことを拡張するために、JVMの終了などを引き起こさないものはすべて、最終的にブロックされます。したがって、次の方法:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
奇妙なことに、コンパイルと1の両方が返されます。
System.exitに関連して、finallyブロックが実行されない特定のタイプの壊滅的な障害もあります。 JVMのメモリが完全になくなると、キャッチまたは最終的に発生せずにJVMが終了する場合があります。
具体的には、愚かにも使用しようとしたプロジェクトを覚えています
catch (OutOfMemoryError oome) {
// do stuff
}
JVMにcatchブロックを実行するためのメモリが残っていないため、これは機能しませんでした。
try { for (;;); } finally { System.err.println("?"); }
その場合、finallyは実行されません(非推奨のThread.stop
が呼び出されるか、同等のものが、たとえばツールインターフェースを介して呼び出されます)。
このスレッドでは、Sunのチュートリアルが誤って引用されています。
注:tryまたはcatchコードの実行中にJVMが終了すると、finallyブロックwill実行されません。同様に、tryコードまたはcatchコードを実行しているスレッドが中断または強制終了された場合、アプリケーション全体が継続しても、finallyブロックwillは実行されません。
最終的にブロックするためにSunのチュートリアルをよく見ると、「実行しない」とは言わず、「実行しない可能性がある」と正しい説明があります。
注:tryまたはcatchコードの実行中にJVMが終了した場合、finallyブロックmay実行されません。同様に、tryコードまたはcatchコードを実行しているスレッドが中断または強制終了された場合、アプリケーション全体が継続していても、finallyブロックmayは実行されません。
この動作の明らかな理由は、system.exit()の呼び出しがランタイムシステムスレッドで処理されるため、jvmのシャットダウンに時間がかかり、スレッドスケジューラが最終的に実行を要求できるためです。最終的には常に実行されるように設計されていますが、jvmをシャットダウンしている場合、最終的に実行される前にjvmがシャットダウンすることがあります。
また、try
ブロック内でデッドロック/ライブロックが発生した場合。
これを示すコードは次のとおりです。
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();
}
}
このコードは次の出力を生成します。
t1 inside lock1
t2 inside lock1
そして「最終的に」印刷されることはありません
Finallyブロックをバイパスできる条件を次に示します。
最後の非デーモンスレッドの例:
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.");
}
}
出力:
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
最終的にブロックコードの実行をブロックする2つの方法があります。
1。 System.exit()を使用します。
2。どういうわけか実行制御がブロックしようとして到達しない場合。
見る:
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");
}
}
}
}
次の場合、finallyブロックは実行されません:-
System.exit(0)
がtry
ブロックから呼び出されたとき。try
ブロックのデッドロック状態最終的にブロックが実行されない他のフリンジケースもあります。
プレイフレームワークに関連して、finallyブロックが実行されないという非常に特殊なケースに遭遇しました。
このコントローラーアクションコードのfinallyブロックは例外の後にのみ呼び出され、呼び出しが実際に成功したときは呼び出されなかったことに驚いた。
try {
InputStream is = getInputStreamMethod();
renderBinary(is, "out.Zip");
catch (Exception e) {
e.printStackTrace();
} finally {
cleanUp();
}
RenderBinary()が呼び出されたときに、おそらくスレッドが終了するか何かです。他のrender()呼び出しでも同じことが起こると思いますが、確認しませんでした。
Try/catchの後にrenderBinary()を移動することで問題を解決しました。さらに調査した結果、playは@Finallyアノテーションを提供し、コントローラーアクションの実行後に実行されるメソッドを作成することが明らかになりました。ここでの注意点は、コントローラーで任意のアクションが実行された後に呼び出されるということです。そのため、常に良い選択とは限りません。