web-dev-qa-db-ja.com

最後にブロックはいつもJavaで実行されますか?

このコードを考慮して、something()がどんなものであっても、finallyブロックが常に実行されることを 確実に にすることができますか?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}
2159
jonny five

はい、finallytryまたはcatchコードブロックの実行後に呼び出されます。

finallyが呼び出されないのは次の場合だけです。

  1. System.exit()を起動した場合
  2. JVMが最初にクラッシュした場合
  3. JVMがtryブロックまたはcatchブロック内で無限ループ(またはその他の中断不可能な非終了ステートメント)に到達した場合
  4. OSがJVMプロセスを強制終了した場合例:UNIXではkill -9 <pid>
  5. ホストシステムが停止した場合例:停電、ハードウェアエラー、OSパニックなど
  6. finallyブロックがデーモンスレッドによって実行され、他のすべての非デーモンスレッドがfinallyが呼び出される前に終了する場合
2415
jodonnell

コード例:

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int test() {
    try {
        return 0;
    }
    finally {
        System.out.println("finally trumps return.");
    }
}

出力:

finally trumps return. 
0
502
Kevin

また、悪い習慣ではありますが、finallyブロック内にreturn文があると、通常のブロックからの他のreturnよりも優先されます。つまり、次のブロックはfalseを返します。

try { return true; } finally { return false; }

Finallyブロックから例外をスローするのと同じことです。

362
MooBob42

これがJava言語仕様からの公式の言葉です。

14.20.2。 try-finallyとtry-catch-finallyの実行

tryブロックを含むfinallyステートメントは、最初にtryブロックを実行することによって実行されます。次に選択肢があります。

  • tryブロックの実行が正常に完了した場合、[...]
  • Vtryが原因でthrowブロックの実行が突然完了した場合
  • tryブロックの実行が他の何らかの理由で突然完了した場合、Rfinallyブロックが実行されます。その後、選択肢があります。
    • Finallyブロックが正常に完了した場合、tryステートメントは理由Rにより突然完了します。
    • finallyブロックがreason Sのために突然完了した場合、tryステートメントはreason Sのために突然完了します( およびreason Rは破棄されます )。

returnの仕様では、実際にこれを明示的に示しています。

JLS 14.17申告書

ReturnStatement:
     return Expression(opt) ;

returnを持たないExpressionステートメント 試行 それを含むメソッドまたはコンストラクターの呼び出し側に制御を移します。

returnを持つExpressionステートメント 試みる それを含むメソッドの呼び出し側に制御権を移す。 Expressionの値がメソッド呼び出しの値になります。

上記の説明では、メソッドまたはコンストラクタ内にtryブロックにtryステートメントが含まれているreturnステートメントがある場合、単なる "transfer control"ではなく、 "試み controlの転送を使用これらのfinallyステートメントのtry文節は、制御がメソッドまたはコンストラクターの呼び出し側に渡される前に、最も内側から外側の順に実行されます。 finally文節が突然完了すると、returnステートメントによって開始された制御の転送が中断される可能性があります。

249

他の応答に加えて、 'finally'はtry..catchブロックによって例外/戻り値を上書きする権利を持つことを指摘することが重要です。たとえば、次のコードは12を返します。

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

同様に、次のメソッドは例外をスローしません。

public static int getMonthsInYear() {
    try {
        throw new RuntimeException();
    }
    finally {
        return 12;
    }
}

次のメソッドはそれをスローしますが:

public static int getMonthsInYear() {
    try {
        return 12;          
    }
    finally {
        throw new RuntimeException();
    }
}
148
Eyal Schneider

上記の例を少し修正してみました。

public static void main(final String[] args) {
    System.out.println(test());
}

public static int test() {
    int i = 0;
    try {
        i = 2;
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
    }
}

上記のコードは次のように出力されます。

最後に切り札が戻ります。
2

これは、return i;が実行されるとiの値が2になるためです。この後、finallyブロックが実行され、12がiに割り当てられ、次にSystem.out outが実行されます。

finallyブロックを実行した後、tryブロックは12を返すのではなく2を返します。これは、このreturn文が再度実行されないためです。

このコードをEclipseでデバッグするのであれば、System.out of finallyブロックを実行した後にreturnブロックのtryステートメントが再度実行されるように感じるでしょう。しかし、そうではありません。単に値2を返します。

109
vibhash

これが Kevinの答え の詳細です。たとえ後に返されるとしても、返される式はfinallyの前に評価されることを知っておくことは重要です。

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
    }
}

出力:

X
finally trumps return... sort of
0
95
WoodenKitty

それが、finallyブロックの全体的な考え方です。もちろん、他の方法で戻るためにスキップされる可能性があるクリーンアップを確実に実行できます。

最後に呼び出されます何が起こっても tryブロックで(unlessSystem.exit(int)またはJavaその他の理由で仮想マシンが起動します)。

53
Chris Cooper

これについて考えるための論理的な方法は、次のとおりです。

  1. Finallyブロックに配置されたコードは、 発生したものすべて tryブロック内で実行する必要があります。
  2. したがって、tryブロック内のコードが値を返すか例外をスローしようとすると、finallyブロックが実行されるまでアイテムは「棚に」置かれます
  3. Finallyブロック内のコードは(定義により)高い優先順位を持っているので、好きなものを返すかスローすることができます。その場合、「棚に」残ったものはすべて破棄されます。
  4. これに対する唯一の例外は、tryブロック中にVMが完全にシャットダウンした場合です。 'System.exit'によって
38
Garth Gilmour

(System.exit(0)を呼び出すように)プログラムの異常終了がない限り、finallyは常に実行されます。だから、あなたのSYSOUTが表示されます

18
shyam

また、やっと戻ってきた場合は、例外がすべて捨てられます。 http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html

18

JVMのクラッシュまたはSystem.exit(0)の呼び出しによってプログラムが異常終了しない限り、finallyブロックは常に実行されます。

それに加えて、finallyブロック内から返される値は、finallyブロックの実行前に返される値をオーバーライドするため、try finallyを使うときはすべての出口点をチェックするように注意してください。

17
user9189

いいえ、必ずしも1つの例外ケースが// System.exit(0)です。 finallyブロックの前にfinallyが実行されるのを防ぎます。

  class A {
    public static void main(String args[]){
        DataInputStream cin = new DataInputStream(System.in);
        try{
            int i=Integer.parseInt(cin.readLine());
        }catch(ArithmeticException e){
        }catch(Exception e){
           System.exit(0);//Program terminates before executing finally block
        }finally{
            System.out.println("Won't be executed");
            System.out.println("No error");
        }
    }
}
17
Rajendra Jadi

それがリターンの後にコードに現れるという理由だけで、最後に常に実行されていることが全体的なポイントです。 Javaランタイムは、tryブロックを終了するときにこのコードを実行する責任があります。

たとえば、次のようになっているとします。

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

ランタイムは次のようなものを生成します。

int foo() {
    int ret = 42;
    System.out.println("done");
    return 42;
}

キャッチされていない例外がスローされた場合、finallyブロックが実行され、例外は伝播し続けます。

12
Motti

これは、iの値を12として割り当てたのに、iの値を関数に返さなかったためです。正しいコードは次のとおりです。

public static int test() {
    int i = 0;
    try {
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
        return i;
    }
}
10
Wasim

System.exit()を呼び出さない限り(またはスレッドがクラッシュするまで)、finallyブロックが常に呼び出されるためです。

9
Jay Riggs

答えは簡単です _ yes _

入力:

try{
    int divideByZeroException = 5 / 0;
} catch (Exception e){
    System.out.println("catch");
    return;    // also tried with break; in switch-case, got same output
} finally {
    System.out.println("finally");
}

出力:

catch
finally
9
Meet

はい、それは呼ばれるでしょう。それがfinallyキーワードを持つことの全体的なポイントです。 try/catchブロックから飛び出してfinallyブロックを飛ばすことができれば、System.out.printlnをtry/catchの外側に置くのと同じことになります。

8
Mendelt

はい、finallyブロックは常に実行されます。開発者のほとんどは、データベース接続、ResultSetオブジェクト、Statementオブジェクトとトランザクションをロールバックするために休止状態また、Javaに使用を閉じ、このブロックを使用します。

8
Gautam Viradiya

簡潔に言えば、公式のJavaドキュメンテーション(Click here )には、 - と書かれています -

Tryまたはcatchコードの実行中にJVMが終了すると、finallyブロックは実行されない可能性があります。同様に、tryまたはcatchコードを実行しているスレッドが中断または強制終了された場合、アプリケーション全体が継続していてもfinallyブロックは実行されないことがあります。

8
bikz05

はいそうでしょう。 JVMが終了またはクラッシュしない場合のみ

7
abhig

はい、できます。他の方法でSystem.exit()が呼び出されるかJVMがクラッシュしない限り、tryまたはcatchブロック内で何が発生しても関係ありません。ブロック内にreturnステートメントがある場合は、そのreturnステートメントの前に最後に実行されます。

7
Karthikeyan

次のプログラムを考えてください。

public class SomeTest {

    private static StringBuilder sb = new StringBuilder();

    public static void main(String args[]) {

        System.out.println(someString());
        System.out.println("---AGAIN---");
        System.out.println(someString());
        System.out.println("---PRINT THE RESULT---");
        System.out.println(sb.toString());
    }

    private static String someString() {

        try {
            sb.append("-abc-");
            return sb.toString();

        } finally {
            sb.append("xyz");
        }
    }
}

Java 1.8.162以降、上記のコードブロックは次のように出力されます。

-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz

これは、オブジェクトを解放するためにfinallyを使用することは、次のコードのように良い習慣であることを意味します。

private static String someString() {

    StringBuilder sb = new StringBuilder();

    try {
        sb.append("abc");
        return sb.toString();

    } finally {
        sb = null; // Just an example, but you can close streams or DB connections this way.
    }
}
7
Samim

私はこれを試した、それはシングルスレッドです。

class Test {
    public static void main(String args[]) throws Exception {
       Object obj = new Object();
       try {
            synchronized (obj) {
            obj.wait();
            System.out.println("after wait()");
           }
       } catch (Exception e) {
       } finally {
           System.out.println("finally");
       }
   }
}

メインスレッドは永遠に待ち状態になるので、最後に呼ばれることはありません。

コンソール出力は文字列を表示しません:after wait()またはfinally

@Stephen Cに同意して、上記の例は3番目のケース言及の1つです ここ

次のコードで、このような無限ループの可能性をさらにいくつか追加します。

// import Java.util.concurrent.Semaphore;
class Test {
    public static void main(String[] args) {
        try {
            // Thread.sleep(Long.MAX_VALUE);
            // Thread.currentThread().join();
            // new Semaphore(0).acquire();
            // while (true){}
            System.out.println("after sleep join semaphore exit infinite while loop");
        } catch (Exception e) {
        } finally {
            System.out.println("finally");
        }
    }
}

ケース2:JVMが最初にクラッシュした場合

import Sun.misc.Unsafe;
import Java.lang.reflect.Field;
class Test {
    public static void main(String args[]) {
        try {
            unsafeMethod();
//            Runtime.getRuntime().halt(123);
            System.out.println("After Jvm Crash!");
        } catch (Exception e) {
        } finally {
            System.out.println("finally");
        }
    }

    private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe) f.get(null);
        unsafe.putAddress(0, 0);
    }
}

Ref: どうやってJVMをクラッシュさせますか?

ケース6:finallyブロックがデーモンスレッドによって実行され、デーモン以外のすべてのスレッドがfinallyが呼び出される前に終了する場合。

class Test {
    public static void main(String args[]) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    printThreads("Daemon Thread printing");
                    // just to ensure this thread will live longer than main thread
                    Thread.sleep(10000);
                } catch (Exception e) {
                } finally {
                    System.out.println("finally");
                }
            }
        };
        Thread daemonThread = new Thread(runnable);
        daemonThread.setDaemon(Boolean.TRUE);
        daemonThread.setName("My Daemon Thread");
        daemonThread.start();
        printThreads("main Thread Printing");
    }

    private static synchronized void printThreads(String str) {
        System.out.println(str);
        int threadCount = 0;
        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        for (Thread t : threadSet) {
            if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
                System.out.println("Thread :" + t + ":" + "state:" + t.getState());
                ++threadCount;
            }
        }
        System.out.println("Thread count started by Main thread:" + threadCount);
        System.out.println("-------------------------------------------------");
    }
}

出力:これは、 "デーモンスレッド"の "最後のブロック"が実行されなかったことを意味する "finally"を表示しません。

main Thread Printing  
Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED  
Thread :Thread[main,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE   
Thread count started by Main thread:3  
-------------------------------------------------  
Daemon Thread printing  
Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE  
Thread count started by Main thread:2  
-------------------------------------------------  

Process finished with exit code 0
6
dkb

はい、 制御文なし finallyの実行を妨げる可能性があるためです。

これは参考例で、すべてのコードブロックが実行されます。

| x | Current result | Code 
|---|----------------|------ - - -
|   |                |     
|   |                | public static int finallyTest() {
| 3 |                |     int x = 3;
|   |                |     try {
|   |                |        try {
| 4 |                |             x++;
| 4 | return 4       |             return x;
|   |                |         } finally {
| 3 |                |             x--;
| 3 | throw          |             throw new RuntimeException("Ahh!");
|   |                |         }
|   |                |     } catch (RuntimeException e) {
| 4 | return 4       |         return ++x;
|   |                |     } finally {
| 3 |                |         x--;
|   |                |     }
|   |                | }
|   |                |
|---|----------------|------ - - -
|   | Result: 4      |

以下の変形では、return x;はスキップされます。結果はまだ4です。

public static int finallyTest() {
    int x = 3;
    try {
        try {
            x++;
            if (true) throw new RuntimeException("Ahh!");
            return x; // skipped
        } finally {
            x--;
        }
    } catch (RuntimeException e) {
        return ++x;
    } finally {
        x--;
    }
}

参照は、もちろん、それらのステータスを追跡します。この例では、value = 4を含む参照を返します。

static class IntRef { public int value; }
public static IntRef finallyTest() {
    IntRef x = new IntRef();
    x.value = 3;
    try {
        return x;
    } finally {
        x.value++; // will be tracked even after return
    }
}
6
Dávid Horváth

finallyが実行され、それは確かです。

以下の場合、finallyは実行されません。

ケース1:

System.exit()を実行しているとき。

ケース2:

あなたのJVM/Threadがクラッシュした時。

ケース3:

手動で実行が途中で停止したとき。

6
Utkash Bhatt

try- catch- finallyは、例外処理を使用するためのキーワードです。
通常の説明文として

try {
     //code statements
     //exception thrown here
     //lines not reached if exception thrown
} catch (Exception e) {
    //lines reached only when exception is thrown
} finally {
    // always executed when the try block is exited
    //independent of an exception thrown or not
}

Finallyブロックが実行を妨げています...

  • System.exit(0);を呼び出したとき
  • JVMが終了した場合.
  • JVMのエラー

例外を処理しない場合は、プログラムを終了する前に、JVMはfinallyブロックを実行します。以下の理由により、プログラムの通常の実行が失敗してプログラムの終了を意味する場合にのみ実行されません.

  1. プロセスを中止させる致命的なエラーを引き起こすことによって。

  2. メモリ破損によるプログラムの終了.

  3. System.exit()を呼び出すことによって

  4. プログラムが無限ループに陥った場合.

6

それはどの言語でも事実です...そのreturnがメソッド本体のどこにあっても、最終的には常にreturn文の前に実行されます。そうでない場合、finallyブロックはあまり意味がありません。

6
Scott Dorman

@ vibhashの答え に他の答えがないので、以下のような可変オブジェクトの場合に何が起こるかを説明します。

public static void main(String[] args) {
    System.out.println(test().toString());
}

public static StringBuffer test() {
    StringBuffer s = new StringBuffer();
    try {
        s.append("sb");
        return s;
    } finally {
        s.append("updated ");
    }
}

出力します

sbupdated 
6

はい、書かれています ここ

Tryまたはcatchコードの実行中にJVMが終了すると、finallyブロックは実行されない可能性があります。同様に、tryまたはcatchコードを実行しているスレッドが中断または強制終了された場合、アプリケーション全体が継続していてもfinallyブロックは実行されないことがあります。

5

Tryブロック内のreturnを最後に置き換える際のreturnについての点に加えて、例外についても同じことが言えます。例外をスローするfinallyブロックは、tryブロック内からスローされたreturnまたはexceptionを置き換えます。

5
Alex Miller

常にではない

Java言語仕様は、try-catch-finallyブロックおよびtry-catchブロックが 14.20.2 でどのように機能するかを記述しています。
いかなる場所でも、finallyブロックが常に実行されることは指定されていません。しかし、try-catch-finallyブロックとtry-finallyブロックが完了するすべての場合において、完了前に最終的に実行しなければならないことを指定します。

try {
  CODE inside the try block
}
finally {
  FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).

JLSは、 _ fin _ _ code _ の後に実行されることを保証しません。 _ code _ および _ next _ が実行されると、 _ fin _ が常に _ code _ の後に実行されることがJLSによって保証されます。そして _ next _ の前。

JLSがfinallyブロックが常にtryブロックの後に実行されることを保証しないのはなぜですか?不可能だからです。 tryブロックが完了した直後、finallyブロックが実行される前に、JVMが中止される(kill、crash、power off)可能性は低いですが可能性があります。これを避けるためにJLSができることは何もありません。

したがって、それらのtryブロックが完了した後に常に実行されている、最終的なブロックに依存する適切な動作のためのソフトウェアにはバグがあります。

Tryブロック内の戻り値は、この問題とは無関係です。 try-catch-finallyの後に実行がコードに到達した場合は、tryブロック内でreturnの有無にかかわらず、finallyブロックが以前に実行されたことが保証されます。

最後のブロックは、System.exit()が最初に呼び出された場合、またはJVMがクラッシュした場合の2つの固有のシナリオでは、復帰後に呼び出されません。

できるだけ簡単な方法であなたの質問に答えようとしましょう。

規則1 :finallyブロックは常に実行されます(ただし例外はありますが、しばらくの間はこれに固執しましょう)。

規則2 :制御がtryブロックまたはcatchブロックを離れたときにfinallyブロック内のステートメントが実行されます。制御の転送は、通常の実行、中断の実行、続行、goto、またはreturnステートメント、または例外の伝播.

Return文の場合(キャプションが付いているので)、コントロールは呼び出し元のメソッドを終了する必要があります。そして、対応するtry-finally構造体のfinallyブロックを呼び出します。 return文はfinallyブロックの後に実行されます。

Finallyブロックにreturn文がある場合、それは呼び出しスタックをクリアするので、tryブロックで保留中のものを確実に上書きします。

あなたはここでより良い説明を参照することができます: http://msdn.Microsoft.com/en-us/ ....概念はすべての高級言語でほとんど同じです。

5
Sandip Solanki
  1. 最後にブロックは常に実行されます。 System.exit() ステートメントが存在しない限り、最後に存在します(finallyブロックの最初のステートメント)。
  2. system.exit() が最初のステートメントの場合、finallyブロックは実行されず、制御はfinallyブロックから出てきます。 System.exit()ステートメントがそのステートメントがfinallyブロック実行されるまでfinallyブロックに入ったときはいつでも、System.exit()が現れたときは制御力がfinallyブロックから完全に出てきます。
5
Avinash Pande

次のコードと同じです。

static int f() {
    while (true) {
        try {
            return 1;
        } finally {
            break;
        }
    }
    return 2;
}

fは2を返します。

4
dibo

なぜならファイナルはあなたが持っているどんな場合でも常に呼ばれるからです。あなたは例外を持っていない、それはまだ呼ばれている、例外をキャッチ、それはまだ呼ばれている

4
vodkhang

はい、常に呼び出されますが、System.exit()を使用したときに呼び出されないことがあります。

try{
//risky code
}catch(Exception e){
//exception handling code
}
finally(){
//It always execute but before this block if there is any statement like System.exit(0); then this block not execute.
}
4

Tryブロックの前に例外が発生した場合、最後にblockは常に例外処理を実行するかどうかにかかわらず実行し、最後にblockは実行されません。

4
Rohit Chugh

例外がスローされた場合は、最後に実行されます。例外がスローされない場合は、最後に実行されます。例外が発生した場合は、最後に実行されます。例外が捕捉されない場合は、最後に実行されます。

実行されないのは、JVMが終了したときだけです。

4
Bhushan

通常の実行の過程でこれを考慮してください(つまり、例外がスローされることはありません)。

4
Gala101

このコードを試してみて、あなたはfinallyブロックの コードがreturn文の後に実行されることを理解するでしょう

public class TestTryCatchFinally {
    static int x = 0;

    public static void main(String[] args){
        System.out.println(f1() );
        System.out.println(f2() );
    }

    public static int f1(){
        try{
            x = 1;
            return x;
        }finally{
            x = 2;
        }
    }

    public static int f2(){
        return x;
    }
}
4
eric2323223

私はさまざまなフォーラムで提供されているすべての回答と非常に混乱していたので、最後にコーディングして表示することにしました。出力は次のとおりです。

try and catchブロックにreturnがあっても、ついに実行されます。

try {  
  System.out.println("try"); 
  return;
  //int  i =5/0;
  //System.exit(0 ) ;
} catch (Exception e) {   
  System.out.println("catch");
  return;
  //int  i =5/0;
  //System.exit(0 ) ;
} finally {  
   System.out.println("Print me FINALLY");
}

出力

やってみる

最後に印刷してください

  1. 上記のコードのtry and catchブロックでreturnがSystem.exit(0)に置き換えられ、その前に何らかの理由で例外が発生した場合。
4
milton

ネストしたfinallyブロック内で例外がスローされた場合は、finallyも途中で終了する可能性があります。コンパイラは、finallyブロックが正常に完了しなかったこと、またはアクセスできないコードがあることを示すエラーを出したことを警告します。到達不能コードのエラーは、throwが条件文の後ろまたはループの内側にない場合にのみ表示されます。

try{
}finally{
   try{
   }finally{
      //if(someCondition) --> no error because of unreachable code
      throw new RunTimeException();
   }
   int a = 5;//unreachable code
}
3

最後はいつも最後に呼ばれる

試してみると、何らかのコードが実行されます。tryで何か問題が発生した場合は、catchがその例外をキャッチし、mssgを出力するかエラーをスローして、最後にblockを実行します。

たとえば、Javaでスキャナーを使用する場合は、スキャナーを閉じる必要があります。ファイルを開けないなどの他の問題が発生する可能性があるためです。

2
Rubin Luitel

tryブロックにreturn文を入れても、最後にblockは常に実行されます。 finallyブロックはreturn文の前に実行されます。

2
Sabrina

Finallyブロックをバイパスできる条件を次に示します。

  1. Tryまたはcatchコードの実行中にJVMが終了すると、finallyブロックが実行されない場合があります。 Sunチュートリアル の詳細
  2. 通常のシャットダウン-これは、Runtime.exit()( some good blog )のときに、最後のデーモン以外のスレッドがORを終了するときに発生します。スレッドが終了すると、JVMは実行中のスレッドのインベントリを実行し、残っているスレッドがデーモンスレッドのみである場合、秩序だったシャットダウンを開始します。 JVMが停止すると、残りのデーモンスレッドはすべて破棄され、最終的にブロックは実行されず、スタックは巻き戻されず、JVMは終了します。デーモンスレッドは、クリーンアップなしでいつでも安全に破棄できる処理アクティビティをほとんど使用しないでください。特に、あらゆる種類のI/Oを実行する可能性のあるタスクにデーモンスレッドを使用することは危険です。デーモンスレッドは、メモリ内キャッシュから期限切れのエントリを定期的に削除するバックグラウンドスレッドなどの「ハウスキーピング」タスクに最適に保存されます( source

最後のデーモン以外のスレッドの例:

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
0