finallyの動作保証

Javaのfinallyブロックについて、StackOveFlowError などの致命的なエラーが発生した場合、どのような挙動になるか自信がなかったので、Twitter上で緩募しました。いくつか回答をいただいたのでまとめました。 回答いただいた皆様ありがとうございます!
3
Takahiro YAMADA @yamadamn

【緩募】Javaのfinallyブロックでの処理は、StackOveFlowError などの致命的なエラーが発生した場合にも、動作することは保証されているのでしょうか?

2012-05-08 12:00:22
ゆとり🇺🇦 @megascus

@yamadamn エラー時の動作は基本的に保証されませんっ アウトオブメモリーを考えれば……

2012-05-08 12:02:35
Takahiro YAMADA @yamadamn

@megascus やはりそうですよねぇ。OOMEはその通りだと思うのですが、他のErrorでも普遍的に言えることか分からなかったので… ありがとうございます。

2012-05-08 12:05:02
ゆとり🇺🇦 @megascus

@yamadamn あー、そういう意味ではfinally句は仕様上動きはします。ただ、きちんと動作していることを期待するのはちょっと危険かなあと。

2012-05-08 12:13:46
ゆとり🇺🇦 @megascus

@yamadamn JVMが正しく動作している上での仕様なので、エラーが出た以上、JVMが正しく動作していると考えてはいけないです。

2012-05-08 12:15:56
Takahiro YAMADA @yamadamn

@megascus はい、おっしゃる通りです。結局finallyは呼び出されたとしても、その中の処理が正常に動作しない可能性があるのじゃ意味ないですよね。

2012-05-08 12:50:29
きむち @kimuchi583

期待するとハマるかも。OOME と同じと思ってます。Error だし。 RT @yamadamn: 【緩募】Javaのfinallyブロックでの処理は、StackOveFlowError などの致命的なエラーが発生した場合にも、動作することは保証されているのでしょうか?

2012-05-08 12:08:37
きむち @kimuchi583

@yamadamn finally 節に書かれた処理がうまく動くかじゃなくて、まずは finally 節に入るかどうかってことだとすると、ちょっとあやふや。

2012-05-08 12:20:52
Takahiro YAMADA @yamadamn

@kimuchi583 ありがとうございます。やはりですかねぇ。仕様として明示されていればよいのですが、見つけれなかったんですよね。

2012-05-08 12:14:05
きむち @kimuchi583

@yamadamn JLS 14.20.2 にあります。3rd Edition も Java SE 7 Edtion も同じで finally ブロックに突入するのが仕様ですね。

2012-05-08 12:59:03
Takahiro YAMADA @yamadamn

@kimuchi583 おぉ、明記されているのですね。ありがとうございます!ここですね。 http://t.co/njvmRI86

2012-05-08 13:08:02
きむち @kimuchi583

@yamadamn デスね。で、finally の処理で異常となると(StackOverflowやOOME では、そうなることが多い)、最初の例外/エラーが握り潰され、finally での例外/エラーが try 文の異常終了の理由になる

2012-05-08 13:06:38
Takahiro YAMADA @yamadamn

@kimuchi583 ふむふむ、そうなんですね。後は簡単に検証してみます!

2012-05-08 13:08:29
工藤俊作 @kudoshunsaku

@yamadamn 確かじゃないですけど、catch節でハンドル出来なければfinally節は実行されないと思います。System.exit()で抜けても実行されないみたいですし。うろ覚えです。探偵の工藤より。

2012-05-08 12:35:07
Takahiro YAMADA @yamadamn

@kudoshunsaku ありがとうございます。System.exit()はその通りなのですが、一般的にErrorが発生した際の仕様が気になったのです。他の方の意見ではfinally節は仕様としては呼び出されるが、その中の処理はErrorですから正しく動作する訳ではないとのこと

2012-05-08 12:56:20
工藤俊作 @kudoshunsaku

@yamadamn 理解しました。有難うございます。仕様では呼び出そうと努力するんですね。catch節に注目したのは、省略すると、finallyが実行されない筈。それだけです。

2012-05-08 13:01:58
Takahiro YAMADA @yamadamn

@kudoshunsaku いや、catch節を省略してもfinally節は呼び出されます。例外は処理しない(上位に任せる)けどfinallyは実行したい、というケースもありますので。

2012-05-08 13:04:16
工藤俊作 @kudoshunsaku

@yamadamn 言葉足りませんでした。例外が発生した場合にcatchがなくてfinallyがある時に実行されないという話を思い出したのです。お時間取らせてしまい失礼致しました。ご容赦下さい。

2012-05-08 13:18:15
Takahiro YAMADA @yamadamn

@kudoshunsaku いえいえ、そのようなことがあるのですね。今回調べたかったケースはそのようなものなので、調査してみます。こちらこそお手数お掛けしましてすみません。ありがとうございました。

2012-05-08 13:20:08
工藤俊作 @kudoshunsaku

@yamadamn 探偵の完全な間違いです。貴殿質問の本題と関係ないですが。catch節無しでもデフォルトの例外処理しますね。更に余談でUncaughtExceptionHandlerてのも実装できるみたいですね。本当に失礼致しました。

2012-05-08 18:04:52
Takahiro YAMADA @yamadamn

@kudoshunsaku わざわざ調べていただいたんですね。。すみません。UncaughtExceptionHandlerはアプリが例外処理をちゃんと行わないときに救済策としてThreadに設定するものですね。今回のfinallyとは趣旨が違いますが、昔実装した覚えがあります。

2012-05-08 18:14:38
Den @den2sn

@yamadamn finallyが呼び出されることは保障されていると思いますがfinallyの処理がうまく動作するかはわからないですね。StackOverflowErrorの場合はfinallyの処理時に問題が解消されていると思うので大丈夫だとは思いますが。

2012-05-08 12:44:37
Takahiro YAMADA @yamadamn

@den2sn ありがとうございます。やはり仕様としてはfinallyが呼び出されることは保証されていそうですね。ただ、Errorなのでその中の処理が動作するかは何とも、というところに落ち着きそうです。後はちょっと検証してみます。

2012-05-08 12:57:56
Takahiro YAMADA @yamadamn

@yamadamn 何人かに情報いただいたのでまとめ。 ・finallyブロック自体はErrorが発生した場合でも呼び出されることがJLS14.20.2で保証されている。 ・Errorなのでfinallyブロック内の処理が正常に実行されるかは保証されない

2012-05-08 13:36:26
Takahiro YAMADA @yamadamn

@yamadamn 補足1) tryおよびcatchの中でSystem.exitが呼び出された場合は、慣例的にfinallyブロックが呼び出されないことが知られている。

2012-05-08 13:40:40