どのような状況でjava.lang.Error
アプリケーションをキャッチする必要がありますか?
16 に答える
一般的に、決して。
ただし、特定のエラーをキャッチする必要がある場合もあります。
フレームワークっぽいコードを書いている (サードパーティのクラスをロードしている) 場合は、キャッチするのが賢明かもしれませんLinkageError
(クラス定義が見つからない、満足できないリンク、互換性のないクラス変更)。
のサブクラスをスローする愚かなサードパーティのコードもいくつか見Error
たので、それらも処理する必要があります。
ちなみに、から回復できないかどうかはわかりませんOutOfMemoryError
。
一度もない。アプリケーションがコードの次の行を実行できるかどうかを確認することはできません。を取得した場合、確実に何かを実行できるという保証はありませOutOfMemoryError
ん。RuntimeException とチェック済みの例外はキャッチしますが、エラーはキャッチしません。
一般に、常にキャッチjava.lang.Error
してログに書き込むか、ユーザーに表示する必要があります。私はサポートの仕事をしていますが、プログラマーがプログラムで何が起こったのか分からないのを毎日見ています。
デーモン スレッドがある場合は、終了しないようにする必要があります。それ以外の場合、アプリケーションは正しく動作します。
java.lang.Error
最高レベルでのみキャッチする必要があります。
エラーのリストを見ると、ほとんどのエラーを処理できることがわかります。たとえば、ZipError
破損した zip ファイルを読み取るときに発生します。
最も一般的なエラーはOutOfMemoryError
とNoClassDefFoundError
で、ほとんどの場合、どちらも実行時の問題です。
例えば:
int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];
を生成できますOutOfMemoryError
が、これは実行時の問題であり、プログラムを終了する理由にはなりません。
NoClassDefFoundError
ほとんどの場合、ライブラリが存在しない場合、または別の Java バージョンを使用している場合に発生します。プログラムのオプション部分である場合は、プログラムを終了しないでください。
Throwable
最上位でキャッチして役立つエラー メッセージを生成することがなぜ良い考えなのか、さらに多くの例を挙げることができます。
マルチスレッド環境では、ほとんどの場合、それをキャッチする必要があります! キャッチしたら、ログに記録し、アプリケーション全体を終了してください! そうしないと、重要な部分を実行している可能性のあるスレッドが停止し、アプリケーションの残りの部分はすべてが正常であると見なします。そこから、多くの望ましくない状況が発生する可能性があります。最小の問題の 1 つは、1 つのスレッドが機能していないために他のスレッドがいくつかの例外をスローし始めた場合、問題の根本を簡単に見つけることができないことです。
たとえば、通常、ループは次のようになります。
try {
while (shouldRun()) {
doSomething();
}
}
catch (Throwable t) {
log(t);
stop();
System.exit(1);
}
場合によっては、さまざまなエラーを別の方法で処理したい場合があります。たとえば、OutOfMemoryError では、アプリケーションを定期的に閉じることができます (場合によっては、一部のメモリを解放して続行することもできます)。他のいくつかのエラーでは、できることはあまりありません。
めったにありません。
スレッドが死んでいる理由を示すメッセージを発行するために、スレッドの最上位でのみ言うと思います。
この種のことを行うフレームワークを使用している場合は、フレームワークに任せてください。
絶対に起きてはならない異常Error
な状態を示しているため、通常はキャッチされません。
Error
クラスの Java API 仕様から:
An
Error
は のサブクラスでありThrowable
、合理的なアプリケーションがキャッチしようとすべきではない重大な問題を示します。このようなエラーのほとんどは異常な状態です。[...]メソッドは、メソッドの実行中にスローされる可能性があるがキャッチされない Error のサブクラスを throws 句で宣言する必要はありません。これらのエラーは決して発生してはならない異常な状態であるためです。
仕様に記載されているように、Error
は次のような状況でのみスローされError
ます。 が発生した場合、アプリケーションでできることはほとんどなく、状況によっては、Java 仮想マシン自体が不安定な状態 ( などVirtualMachineError
)になる可能性があります。
anError
はそのサブクラスですがThrowable
、句によって捕捉できることを意味しますが、JVM によってtry-catch
anError
がスローされるとアプリケーションが異常な状態になるため、おそらく実際には必要ありません。
Section 11.5 The Exception Hierarchy of the Java Language Specification, 2nd Editionにも、このトピックに関する短いセクションがあります。
新しい単体テスト フレームワークを作成することに夢中になっている場合、テスト ランナーはおそらく、すべてのテスト ケースによってスローされた java.lang.AssertionError をキャッチする必要があります。
それ以外の場合は、他の回答を参照してください。
ほとんどは決してない。エラーは、アプリケーションが通常何もできない問題になるように設計されています。唯一の例外は、エラーの表示を処理することかもしれませんが、それでもエラーによっては計画どおりに進まない場合があります。
また、エラーをキャッチした場合、それを再スローする必要がある場合が他にもいくつかあります。たとえば、ThreadDeathは決してキャッチされるべきではありません。封じ込められた環境 (アプリケーション サーバーなど) でキャッチすると、大きな問題が発生する可能性があります。
アプリケーションは、非同期で終了した後にクリーンアップする必要がある場合にのみ、このクラスのインスタンスをキャッチする必要があります。ThreadDeath がメソッドによってキャッチされた場合、スレッドが実際に終了するように再スローすることが重要です。
非常に、非常にまれです。
私は非常に特定の既知のケースに対してのみそれを行いました。たとえば、2 つの独立した ClassLoaderが同じ DLL をロードすると、java.lang.UnsatisfiedLinkError がスローされる可能性があります。(JAR を共有クラスローダーに移動する必要があることに同意します)
しかし、最も一般的なケースは、ユーザーが苦情を申し立てたときに何が起こったのかを知るためにログが必要だったということです。黙って死ぬのではなく、ユーザーへのメッセージまたはポップアップが必要です。
C/C++ のプログラマーでさえ、エラーをポップして、終了する前に人々が理解できないことを伝えます (例: メモリ障害)。
テスト環境で java.lang.AssertionError をキャッチすると非常に便利です...
Android アプリケーションで、 java.lang.VerifyErrorをキャッチしています。私が使用しているライブラリは、OS の古いバージョンのデバイスでは動作せず、ライブラリ コードはこのようなエラーをスローします。もちろん、実行時に OS のバージョンを確認することでエラーを回避できますが、次のようになります。
- サポートされている最も古い SDK は、特定のライブラリについて将来変更される可能性があります。
- try-catch エラー ブロックは、より大きなフォールバック メカニズムの一部です。一部の特定のデバイスは、ライブラリをサポートするはずですが、例外をスローします。VerifyError とすべての例外をキャッチして、フォールバック ソリューションを使用します。
理想的には、エラーを処理/キャッチすべきではありません。ただし、フレームワークまたはアプリケーションの要件に基づいて、行う必要がある場合があります。より多くのメモリを消費するDOM パーサーを実装する XML パーサー デーモンがあるとします。パーサー スレッドがOutOfMemoryErrorを取得したときに停止してはならないなどの要件がある場合は、代わりにそれを処理し、アプリケーション/フレームワークの管理者にメッセージ/メールを送信する必要があります。
JVM が期待どおりに動作しなくなった場合、または動作する寸前である場合、エラーが発生します。エラーをキャッチした場合、catch ブロックが実行される保証はなく、最後まで実行される保証はさらにありません。
また、実行中のコンピューター、現在のメモリの状態にも依存するため、テストして最善を尽くす方法はありません。危険な結果しか得られません。
コードの可読性も低下します。
理想的には、エラーは異常な状態であるため、Java アプリケーションでエラーをキャッチしないようにする必要があります。アプリケーションは異常な状態になり、カーッシングや重大な間違った結果をもたらす可能性があります。