[解決済み] なぜexception.printStackTrace()はバッドプラクティスと考えられているのですか?
疑問点
多くの 材料 アウト そこ で、例外のスタックトレースを表示することは悪い習慣であることを示唆しています。
例:CheckstyleのRengexpSinglelineチェックから。
このチェックは、ex.printStacktrace()を呼び出すような一般的な悪い習慣を見つけるために[...]使用することができます。
しかし、確かにスタックトレースは例外を引き起こしたものを追跡するのに非常に有用であるため、正当な理由を与えてくれる場所を見つけるのに苦労しています。私が認識していること。
-
スタックトレースはエンドユーザーから決して見えないようにすべきです (ユーザーエクスペリエンスとセキュリティのため)
-
スタック トレースの生成は比較的高価な処理です (ただし、ほとんどの「例外的な」状況で問題になることはほとんどありません)。
-
多くのロギングフレームワークは、あなたのためにスタックトレースを表示します (私たちのフレームワークはそうしませんし、簡単に変更することもできません)。
-
スタックトレースを印刷することは、エラー処理を構成しません。 他の情報ロギングや例外処理と組み合わせる必要があります。
あなたのコードでスタックトレースを表示しないようにする他の理由は何ですか?
どのように解決するのですか?
Throwable.printStackTrace()
にスタックトレースを書き込む。
System.err
PrintStream。は
System.err
ストリームと、JVMプロセスの基礎となる標準的な "error"出力ストリームは、次のようにリダイレクトすることができます。
-
呼び出す
System.setErr()
が指す先を変更するSystem.err
. -
または、プロセスのエラー出力ストリームをリダイレクトすることによっても可能です。エラー出力ストリームはファイル/デバイスにリダイレクトされるかもしれません。
- その内容は担当者によって無視されるかもしれません。
- ファイル/デバイスの既存のコンテンツをアーカイブする前に、開いているファイル/デバイスのハンドルを閉じるためにプロセスの再起動が必要であることを推測させる、ログ ローテーションが可能でない可能性があります。
-
の場合のように、ファイル/デバイスに書き込まれたすべてのデータを実際に破棄してしまうこともあります。
/dev/null
.
上記から推論すると
Throwable.printStackTrace()
を呼び出すことは、有効な(良くも悪くもない)例外処理動作であり、唯一
-
がない場合は
System.err
がアプリケーションのライフタイム中ずっと再割り当てされている場合。 - で、アプリケーションの実行中にログのローテーションを必要としない場合。
-
に書き、アプリケーションのロギングの習慣を受け入れて設計されている場合は
System.err
(そして、JVMの標準エラー出力ストリーム)に書き込まれます。
ほとんどの場合、上記の条件は満たされません。JVM で実行されている他のコードを認識していない可能性があり、ログ ファイルのサイズまたはプロセスの実行時間を予測することができず、うまく設計されたロギング練習は、サポートを助けるために、既知の宛先に "機械解析可能" ログ ファイル (ロガーでは望ましいがオプション機能) を書くことで展開されます。
最後に、以下の出力を覚えておく必要があります。
Throwable.printStackTrace()
に書かれた他のコンテンツと確実に混在することになります。
System.err
(に書かれた他のコンテンツ(そしておそらく
System.out
を含む)。これは(シングルスレッド アプリケーションにとって)対処しなければならない厄介な問題で、例外に関連するデータはこのようなイベントで簡単に解析できないからです。さらに悪いことに、マルチスレッド アプリケーションでは、次のような非常にわかりにくいログが生成される可能性が高いです。
Throwable.printStackTrace()
がスレッドセーフでない
.
へのスタックトレースの書き込みを同期させる機構はありません。
System.err
への書き込みを同期させる機構はありません。
Throwable.printStackTrace()
を同時に呼び出したとき。この問題を解決するためには、実際には
System.err
に関連付けられたモニター上で同期する必要があります (そしてまた
System.out
も)、そしてそれはログファイルの正しさのために支払うべきかなり重い代償です。一例を挙げると
ConsoleHandler
と
StreamHandler
クラスは、コンソールにログレコードを追加する役割を担っています。
java.util.logging
ログレコードを発行する実際の操作は同期化されており、ログレコードを発行しようとするすべてのスレッドは、ログレコードの発行に関連するモニタのロックを取得する必要があります。
StreamHandler
インスタンスに関連付けられたモニターのロックを取得する必要があります。を使用してインターリーブされていないログレコードを持つのと同じ保証を得たい場合は、以下のようになります。
System.out
/
System.err
を使用する場合、同じことを保証する必要があります - メッセージは、シリアライズ可能な方法でこれらのストリームに発行されます。
上記のすべて、および
Throwable.printStackTrace()
が実際に有用である非常に限定されたシナリオを考慮すると、それを呼び出すことはしばしば悪い習慣であることがわかります。
前の段落の議論を発展させると、それはまた、以下のような悪い選択です。
Throwable.printStackTrace
をコンソールに書き込むロガーと一緒に使用するのは、あまり良い選択ではありません。これは、ロガーが別のモニター上で同期する一方で、アプリケーションは (おそらく、インターリーブされたログ レコードが必要ない場合は) 別のモニター上で同期するという理由によるものです。この議論は、アプリケーションで、同じ宛先に書き込む 2 つの異なるロガーを使用する場合にも当てはまります。
関連
-
コミットには何も追加されないが、未追跡のファイルが存在し、gitで未追跡のファイルに対する完璧な解決策
-
[解決済み] この2回(1927年)を引き算すると、なぜおかしな結果になるのでしょうか?
-
[解決済み] なぜパスワードにはStringではなくchar[]が好まれるのですか?
-
[解決済み] serialVersionUIDとは何ですか、またなぜそれを使用する必要がありますか?
-
[解決済み] B "の印刷が "#"の印刷より劇的に遅いのはなぜですか?
-
[解決済み] リフレクションとは何か、なぜ有用なのか?
-
[解決済み] ランダムな文字列を使用するこのコードは、なぜ "hello world" と表示されるのですか?
-
[解決済み] なぜゲッターとセッター/アクセッサーを使うのですか?
-
[解決済み] 静的変数が悪とされるのはなぜですか?
-
[解決済み】なぜJavaの+=, -=, *=, /=複合代入演算子はキャスティングを必要としないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Java Exceptionが発生しました エラー解決
-
java の例外が発生しました java
-
javaの実行中に「javaの例外が発生しました」と表示された場合はどうすればよいですか?
-
アクセス制限について アプリケーションの種類がAPIでない(必要なライブラリの制限)。
-
Dateが型に解決できない問題を解決する
-
Javaクラスローダーにソースコードから潜り込む
-
エラーの解決方法 jarfile XXX.jarにアクセスできません。
-
このラインで複数のマーカーを解決する方法
-
maven プラグイン エラー プラグインの実行は、ライフサイクル構成ソリューションの対象外です。
-
[解決済み] JavaにおけるprintStackTrace()メソッドの用途は何ですか?