34

Javatry{} ... catch{} ... finally{}ブロックでfinally{}は、一般に、内のコードは、try/catchで何が発生したかに関係なく実行されることが「保証されている」と見なされます。ただし、実行されない状況が少なくとも2つあることを私は知っています。

  • 呼び出された場合System.exit(0); また、
  • 例外がJVMまでスローされ、デフォルトの動作が発生した場合(つまり、printStackTrace()終了)

ブロック内のコードの実行を妨げる他のプログラムの動作はありますfinally{}か?コードはどのような特定の条件下で実行されますか?

編集: NullUserExceptionが指摘したように、2番目のケースは実際には真ではありません。標準エラーのテキストがその後標準出力で印刷され、上にスクロールせずにテキストが表示されないためだと思いました。:)お詫びします。

4

9 に答える 9

37

呼び出すとSystem.exit()、プログラムは呼び出されずにすぐに終了しますfinally

セグメンテーション違反などのJVMクラッシュも、最終的に呼び出されるのを防ぎます。つまり、JVMはこの時点ですぐに停止し、クラッシュレポートを生成します。

無限ループは、最終的に呼び出されることも防ぎます。

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()の後でも、スレッドは実行を続けました。

于 2012-09-14T19:22:40.777 に答える
9

tryブロック内の無限ループ。

破損したRAM?プログラムは記述どおりに実行されなくなりましたか?私は実際にDOSマシンで一度デバッグしました。

于 2012-09-14T19:18:28.800 に答える
2

tryブロックの別のステートメントでfinallyブロックをテストします。

 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");
    }

finallyブロックが実行されるステートメントは次のとおりです。

  1. Thread.currentThread().interrupted();
  2. Thread.currentThread().destroy();
  3. Thread.currentThread().stop();
  4. Thread.sleep(10);
  5. Thread.currentThread().interrupt();
  6. Runtime.getRuntime().addShutdownHook(Thread.currentThread());
  7. 例外が発生した場合。
  8. 例外がない場合。

finallyブロックが実行されないステートメントは次のとおりです。

  1. Thread.currentThread().suspend();
  2. System.exit(0);
  3. JVMがクラッシュしました。
  4. CPUチップへの電源が切れます。
  5. OSはJVMプロセスを強制終了します。
  6. Runtime.getRuntime().exit(0);
  7. Runtime.getRuntime().halt(0);
于 2017-10-01T10:06:19.587 に答える
1

最終的にそれ自体が例外をスローする(またはエラーにつながる)場合、部分的に実行される可能性があります

于 2012-09-14T19:20:16.487 に答える
1

「最終的には大門スレッドの一部であり、実行されない可能性があります」などが考えられます。

于 2012-09-14T19:41:15.907 に答える
1

最終的に呼び出されないのは次の場合のみです。

電源が切れた場合

  1. System.exit()を呼び出す場合
  2. JVMが最初にクラッシュした場合
  3. tryブロックに無限ループがある場合
  4. 電源が切れた場合
于 2016-12-01T06:33:49.797 に答える
0

なんらかの理由でJVMが突然終了した場合、それが原因で、コントロールがfinallyブロックに入り、実行されない可能性があると思います。

于 2013-05-02T04:16:23.960 に答える
0

デーモンスレッドの一部にすることができます。setDaemon(boolean status)現在のスレッドをデーモンスレッドまたはユーザースレッドとしてマークし、必要に応じてJVMを終了するために使用される方法を使用できます。これにより、finally{}実行前にJVMを終了できます。

于 2013-12-21T18:18:07.467 に答える
0

実行されないfinallyブロックの別の可能性のあるインスタンスは、時々見た非常に悪いコードの場合のように、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...
    }

誰もこれをやらないことを知っているので、これを可能なシナリオとして追加することを躊躇しましたが、ええと、金曜日だと思いました。)。

于 2017-11-04T01:11:18.467 に答える