web-dev-qa-db-ja.com

Javaでは、「finally」ブロックが(mainメソッドで)呼び出されることが保証されていますか?

私はJava新人で、次の典型的なJavaコードがあるかどうか疑問に思っていました

public class MyApp {
  public static void main(String[] args) {
    try {
      // do stuff
    } catch {
      // handle errors
    } finally {
      // clean up connections etc.
    }
  }
}

jVMは、finallyブロックが常に実行されることを保証しますか?私がどこから来たのかを理解するために、私はC/C++プログラムに慣れています。これは、NULLポインターを逆参照するとクラッシュする可能性があり、その後に実行するコードがありません。

しかし、私が理解しているように、JavaおよびGC /マネージドメモリビジネス全体は、一般に、nullポインタの逆参照のようなものはなく、すべてがキャッチ可能な期待であるため、私のプログラムには実際には方法がありませんクラッシュすると、最終的にスキップする可能性がありますか、それともありますか?たとえば、Pythonでは、通常、

try:
  # do stuff
except AnExceptionIKnewMightHappen:
  # react in an appropriate way
except:
  # log that weird error I had not known could happen

コードを渡さずにアプリが死ぬことは一度もありません。

もちろん、OSが何らかの理由でプロセスを強制終了した場合(またはプラグを抜くなど、何かがシステム全体を強制終了した場合)、Javaでできることはあまりありません。また、from PHPインタプリタが発生した後もそこにいたとしても、保護できないキャッチ不可能なエラーを知っています(少なくとも適切なメッセージを出力することができます)。

編集:わかりやすくするために(誰にも誤解されていませんでした)、コード内でものを探していたことを付け加えておきますそれは最終的にバイパスされることにつながる可能性があります。そのため、System.exitをポイントすることは、なぜそのようなことをしたいのかわからない場合でも、役立つリマインダーでした。

JVMの終了はかなり明白な方法であり、私はそれを外部の原因として数えます。 JVMとアプリの実行中にスレッドが終了する可能性も覚えておく必要があることを指摘するメモは非常に役に立ちました。これは、今では明らかなように思えますが、私はそれについて考えていなかったためです。

24
Hanno Fietz

注を除いて、基本的にはい ここにリストされています (私の強調):

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

45
user44484

保証されていません:

public class Main {
    public static void main(String args[]) {
        try {
            System.out.println("try");
            System.exit(0);
        } catch (Exception e) {
            System.out.println("exception");
        } finally {
            System.out.println("finally");
        }
    }
}

それを実行します。

13
cletus

一言で言えば、そうです。

Javaのfinallyブロックのコードは、次の場合を除いて常に実行されます。

  • JVMは、tryまたはcatchブロック中に終了します
  • コードを実行しているスレッドは、tryまたはcatchブロック中に中断または強制終了されます

(from: http://Java.Sun.com/docs/books/tutorial/essential/exceptions/finally.html

したがって、明示的にSystem.exit(int)を呼び出すか、プロセスまたはスレッドを外部で強制終了しない限り、それを信頼できます。

10
Martin McNulty

絶対に、その最終ブロックは毎回実行されます。 JVMがクラッシュした場合、またはexit()関数が呼び出された場合を除きます。 JavaアプリケーションがセグフォールトしたJNIネイティブコードを呼び出したコードがありました。その結果、クラッシュによってJVMが強制終了され、最終的に実行できなくなりました。

4
Arcane

クリスキャメロンは正しいです。ただし、通常はfinally-ブロックが実行されます。ヌルポインタの逆参照はJavaに存在します:

try {
    List<Object> x = null;
    x.get(1); //throws the unchecked NullPointerException
} finally {
    //will be executed
}

Finally-Blockが実行されます。

2
Johannes Weiss

はい、JVMは常にそれを実行します。保証。

もちろん... JVM itselfが停止した場合(例:System.exit())、それは何も保証する立場にありません。しかし、JVMの停止はJava内の問題ではありません。

1
paulmurray

nothing moreがJVMの終了後に実行されるか、その強制終了されたスレッドでコードが実行されることは明らかです。明らかです。したがって、JVMが実行されているときは、実行されるすべてのコードが実行され、JVMが終了した後、またはデッドスレッド内で、nothingが実行されます。これは、どのような種類のコードでも実行されます。したがって、防ぐ方法はありませんが、finally節が必要な場合は、それを入れてください。

0
backslash

最終的にブロックが実行されない唯一の例外は、JVMがクラッシュするか、system.exit()です。

0
lwpro2

えーと、うん:)コードがキャッチに入るかどうかに関係なく、finallyが実行されます。試行後にクリーンアップするコードを配置するのに適した場所です。

明らかに、jvmを壊すと実行されません:)

0
Robert Grant

はい、JVMのクラッシュがない限り、finallyブロックは常に実行されます(非常にまれですが、発生する可能性があります)。

0
Guillaume