java.lang.Errorをいつキャッチするか?


回答:


101

一般的にはありません。

ただし、特定のエラーをキャッチする必要がある場合があります。

フレームワーク風のコード(サードパーティのクラスをロードする)を作成している場合は、キャッチするのが賢明ですLinkageError(クラス定義が見つからない、リンクに満足できない、互換性のないクラスの変更)。

のサブクラスをスローする愚かなサードパーティのコードもいくつか見たErrorので、それらも処理する必要があります。

ちなみに、から復旧できないかどうかはわかりませんOutOfMemoryError


3
DLLをロードするために正確に実行する必要があったこと、DLLが正しく構成されていないと失敗すること。このアプリケーションの場合、致命的なエラーではありません。
MarioOrtegón2008

7
たとえば、大きな配列リストを作成している場合など、OutOfMemoryErrorをキャッチすることが理にかなっていることがあります。
SpaceTrucker 2013年

3
@SpaceTrucker:そのアプローチはマルチスレッドアプリケーションでうまく機能しますか、それとも他のスレッドでの小さな割り当てが失敗するという重大なリスクがありますか?…おそらく、配列が割り当てられるのに十分小さいだけで、他の誰にも何も残していない場合のみです。
PJTraill 2015年

@PJTraillよくわかりません。これには、実際の統計サンプルが必要です。私はそのようなコードを見たと思っていましたが、どこにあったのか思い出せません。
SpaceTrucker 2015年

51

決して。アプリケーションが次のコード行を実行できるかどうかを確認することはできません。を取得した場合OutOfMemoryError確実に何かを実行できるという保証はありません。RuntimeExceptionをキャッチして例外をチェックしましたが、エラーは発生しません。

http://pmd.sourceforge.net/rules/strictexception.html


27
絶対とは絶対言うな。「falseをアサート」するテストコードがあります。次に、AssertionErrorをキャッチして、-eaフラグが設定されていることを確認します。それ以外は...ええ、たぶん決して;-)
Outlaw Programmer

3
リクエストをワーカースレッドに渡すサーバーアプリケーションはどうでしょうか。エラーをトラップするためにワーカースレッドでThrowableをキャッチし、少なくとも何が問題になっているのかをログに記録しても意味がないのではないでしょうか。
リー

11
絶対に必要な場合を除いて... 決して強い言葉ではなく、ルールには常に例外があります。フレームワークを構築している場合、たとえログを記録するだけであっても、特定のエラーをキャッチして処理する必要がある可能性はそれほど高くありません。
ロビン

サードパーティのライブラリメソッドから発生するNoSuchMethodErrorなどのエラーはどうですか?
ha9u63ar

:@OutlawProgrammer念のため、同じテストを行うための他の方法があるboolean assertionsEnabled = false; assert assertionsEnabled = true;
shmosel

16

通常は、常にキャッチjava.lang.Errorしてログに書き込むか、ユーザーに表示する必要があります。私はサポートで働いており、プログラマーがプログラムで何が起こったかを知ることができないことを毎日見ています。

デーモンスレッドがある場合は、終了しないようにする必要があります。それ以外の場合、アプリケーションは正しく動作します。

java.lang.Error最高レベルでのみキャッチする必要があります。

エラーのリストを見ると、ほとんどが処理できることがわかります。たとえば、ZipError破損したzipファイルの読み取り時に発生します。

最も一般的なエラーはOutOfMemoryErrorand NoClassDefFoundErrorであり、どちらもほとんどの場合ランタイムの問題です。

例えば:

int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];

を生成できOutOfMemoryErrorますが、これは実行時の問題であり、プログラムを終了する理由はありません。

NoClassDefFoundErrorほとんどの場合、ライブラリが存在しない場合、または別のバージョンのJavaを使用している場合に発生します。プログラムのオプションの部分である場合は、プログラムを終了しないでください。

Throwableトップレベルでキャッチし、有用なエラーメッセージを生成することがなぜ良いのかについて、さらに多くの例を挙げられます。


私はそれはそれはそれは本当に生きているとやって何かであるという誤った口実を与えるかもしれない失敗したJVM上でいくつかのエーテル幽霊として生きて滞在の可能性を持つように適切な警告とデーモンを失敗するような場合でのより良い疑うだろう
アンドリューノーマン

OutOfMemoryErrorランタイムエラーではないため、アプリケーションがエラーから回復できるという保証はありません。運new byte[largeNumber]が良ければOOMを取得できますが、その割り当てがOOMを引き起こすのに十分でない場合は、次の行または次のスレッドでトリガーされる可能性があります。lengthが信頼できない入力である場合、を呼び出す前に検証する必要があるため、これは実行時の問題new byte[]です。
Jeeyoung Kim 2016

NoClassDefFoundErrorコンパイルされたJavaコードがクラスを見つけられないときに呼び出されるため、どこでも発生する可能性があります。JDKが正しく構成されていない場合は、java.util.*クラスを使用しようとすることがあり、それに対してプログラミングすることは事実上不可能です。オプションで依存関係を含める場合は、を使用ClassLoaderして、それが存在するかどうかを確認する必要がありClassNotFoundExceptionます。
Jeeyoung Kim

1
ZipErrorクラスを含むjarファイルが破損したzipファイルであることを示します。これは非常に深刻な問題であり、現時点では実行されるコードを信頼することはできず、コードから「回復」しようとすることは無責任です。
Jeeyoung Kim 2016

2
一般に、キャッチするjava.lang.Errorjava.lang.Throwable、最上位でそれを使って何かをしようとすると役立ちます。たとえば、エラーメッセージをログに記録します。しかし、その時点では、これが実行されるという保証はありません。JVMがOOMである場合、ログを記録しようとすると、より多くStringのが割り当てられ、別のOOMがトリガーされます。
Jeeyoung Kim

15

マルチスレッド環境では、ほとんどの場合、それをキャッチする必要があります。キャッチしたら、ログに記録して、アプリケーション全体を終了してください!これを行わないと、いくつかの重要な部分を実行している可能性があるスレッドが停止し、アプリケーションの残りの部分はすべて正常であると見なします。その中で、多くの望ましくない状況が発生する可能性があります。1つの最小の問題は、1つのスレッドが機能していないために他のスレッドがいくつかの例外をスローし始めた場合、問題の根本を簡単に見つけることができないことです。

たとえば、通常、ループは次のようになります。

try {
   while (shouldRun()) {
       doSomething();
   }
}
catch (Throwable t) {
   log(t);
   stop();
   System.exit(1);
}

場合によっては、さまざまなエラーを別の方法で処理する必要があります。たとえば、OutOfMemoryErrorでは、アプリケーションを定期的に閉じることができます(メモリを解放して続行することもできます)。


1
プログラムが未定義の状態になるためすぐに存在するのではなくキャッチOutOfMemoryError して続行することは賢明ではありません。
Raedwald、2015年

1
システムを呼び出し、スロー可能オブジェクトをキャッチして終了すると、問題のアプリケーションだけでなく、JVMで実行されているすべてが強制終了されるという予期しない結果が生じます。通常、他のウェブアプリケーションと一緒にアプリサーバーでホストされる可能性のあるウェブアプリケーションにはお勧めできません(アプリサーバー自体に影響することは言うまでもありません)。
Andrew Norman

9

めったにありません。

スレッドが停止した理由をメッセージで表示するために、スレッドの最上位レベルでのみ言います。

このようなことを行うフレームワークを使用している場合は、フレームワークに任せてください。


6

ほとんどは決してない。エラーは、アプリケーションが通常何もできない問題となるように設計されています。唯一の例外は、エラーの表示を処理することですが、エラーによっては、それが計画どおりに実行されない場合もあります。


6

Error通常はキャッチすべきではない、それは同様に、発生することはありません異常な状態を示します

ErrorクラスのJava API仕様から:

ErrorサブクラスであるThrowable ことが合理的なアプリケーションは、キャッチすべきではないという重大な問題を示します。このようなエラーのほとんどは異常な状態です。[...]

これらのエラーは発生してはならない異常な状態であるため、メソッドのthrows句でメソッドの実行中にスローされてもキャッチされないErrorのサブクラスをメソッドで宣言する必要はありません。

仕様に記載されているように、Errorがスローされるのは、Error発生した場合にアプリケーションで実行できることはほとんどなく、状況によっては、Java仮想マシン自体が不安定な状態になる場合があります(などVirtualMachineError

ErrorサブクラスであるのThrowableそれがでキャッチすることができることを意味しtry-catchたときにアプリケーションが異常な状態になりますよう、句が、それはおそらく本当に必要ありませんErrorJVMによってスローされます。

セクション11.5 Java言語仕様の第2版の例外階層にも、このトピックに関する短いセクションがあります。


6

新しい単体テストフレームワークを作成するのに十分夢中になっている場合、テストランナーはおそらく、テストケースによってスローされるjava.lang.AssertionErrorをキャッチする必要があります。

それ以外の場合は、他の回答を参照してください。


5

また、他にもエラーをキャッチした場合に再スローする必要ある場合がいくつかあります。たとえば、ThreadDeathは決してキャッチされるべきではありません。それは、含まれている環境(アプリケーションサーバーなど)でキャッチすると大きな問題を引き起こす可能性があります。

アプリケーションは、非同期的に終了した後にクリーンアップする必要がある場合にのみ、このクラスのインスタンスをキャッチする必要があります。ThreadDeathがメソッドによってキャッチされた場合、スレッドが実際に停止するように再スローすることが重要です。


2
単にsを捕まえないので、これは実際には問題ではありませんError
Bombe

4

非常に、非常にまれです。

私は、非常に具体的な既知の1つのケースに対してのみそれを行いました。たとえば、2つの独立したClassLoaderが同じDLLをロードすると、java.lang.UnsatisfiedLinkErrorがスローされる可能性があります。(JARを共有クラスローダーに移動する必要があることに同意します)

しかし、最も一般的なケースは、ユーザーが不平を言うようになったときに何が起こったかを知るためにロギングが必要だったということです。静かに死ぬのではなく、ユーザーにメッセージまたはポップアップを送りたい。

C / C ++のプログラマーでさえ、エラーを表示し、終了する前に理解できないこと(たとえば、メモリ障害)を知らせます。


3

Androidアプリケーションでjava.lang.VerifyErrorをキャッチしています。私が使用しているライブラリは、古いバージョンのOSを搭載したデバイスでは機能せず、ライブラリコードはそのようなエラーをスローします。もちろん、実行時にOSのバージョンを確認することでエラーを回避できましたが、

  • サポートされている最も古いSDKは、特定のライブラリについて将来変更される可能性があります
  • try-catchエラーブロックは、より大きなフォールバックメカニズムの一部です。一部の特定のデバイスは、ライブラリをサポートすることになっていますが、例外をスローします。VerifyErrorとすべての例外をキャッチして、フォールバックソリューションを使用します。

3

テスト環境でjava.lang.AssertionErrorをキャッチするのは非常に便利です...


追加しようとしている価値は何ですか?
lpapp 2013年

中止しないテストスイートの値を追加
Jono

2

理想的には、エラーを処理/キャッチしないでください。ただし、フレームワークまたはアプリケーションの要件に基づいて、必要な場合があります。たとえば、より多くのメモリを消費するDOMパーサーを実装するXMLパーサーデーモンがあるとします。パーサースレッドのような要件がある場合OutOfMemoryErrorを取得したときにスレッドを停止せず、処理して、アプリケーション/フレームワークの管理者にメッセージ/メールを送信する必要があります。


1

異常な状態であるため、Javaアプリケーションでエラーをキャッチしないことが理想的です。アプリケーションは異常な状態になり、削ったり、深刻な誤った結果をもたらす可能性があります。


1

アサーションが行われたことを確認する単体テスト内でエラーをキャッチすることが適切な場合があります。誰かがアサーションを無効にするか、他の方法でアサーションを削除した場合、知りたい


1

JVMが期待どおりに機能していないか、JVMが限界に近づいているときにエラーが発生します。エラーをキャッチした場合、catchブロックが実行される保証はなく、最後まで実行される保証はありません。

また、実行中のコンピューター、現在のメモリの状態にも依存するため、テストして最善を尽くす方法はありません。あなたは厄介な結果しか得られません。

また、コードの可読性をダウングレードします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.