3

Java の標準クラスの例外の安全性に関する詳細を取得する方法はありますか? 主に C++ と C# を使用しており、Java の例外仕様について混乱しているため、例外の適切な処理方法を理解する必要があります。

より具体的に考えてみましょうServerSocket。オブジェクトが構築されるとすぐに、着信接続のリッスンを開始します。次に、accept()接続を受け入れるために使用する必要があります (誰かが接続しようとした場合)。

以前に でサーバー ソケットを構成したことがある場合は、指定された時間内に誰も接続を試みなかったため、スローさsetSoTimeout()れる変更があります。それは問題ありません。サーバー ソケットはまだ使用できるので、もう一度呼び出すだけです。accept()SocketTimeoutExceptionaccept()

しかし、投げるSocketTimeoutExceptionことができるのはそれだけではありません。accept()他のすべての例外はどういう意味ですか? accept()への呼び出しを2 つの catch 句でラップする場合: forSocketTimeoutExceptionIOException、句に入った後でも関連するインスタンスを安全に使用できますか?ServerSocketIOException

Java全体とServerSocket固有の両方の回答をいただければ幸いです。

4

6 に答える 6

3

オブジェクトを再利用するのは安全ではありません。そのような質問については、私は常に情報源を調べます。それが公開されている理由です。

したがって、それを調べると、http://kickjava.com/src/java/net/ServerSocket.java.htmaccept()、ソケットが閉じられているかバインドされていない場合に SocketException (IOException から継承) がスローされることがわかります。どちらの状態も、ServerSocket が無効になったことを示しています。

したがって、このクラスでは、通常、例外で失敗した場合は、常に最終ブロックで ServerSocket を適切に閉じてから再作成するようにしてください。

さらに、Java全体の質問範囲について:常にソースを調べて、インターフェースが何をしているのかを理解してください。動作を再現するミッション クリティカルな書き込みテストの場合 (このような低レベルの API ではまったく簡単ではないはずです)。

最後に - Java は一貫してそのようなことを行っていますか? いいえ。ステートレスなクラスもあれば、そうでないクラス (ServerSocket など) もあれば、スレッドセーフなクラスもあれば、そうでないクラスもあります。そして、ドキュメントまたは (ほとんどの場合) コードから、例外によってメイン パスから外れてしまった場合に何をすべきかを理解するために、それらが構築する状態を理解する必要があります。

ほとんどの人は、これらのチェック済み Java 例外をののしります。なぜなら、それらのほとんど (ほとんどの IOExceptions と同様) は、実際には意味のある方法で回復できないからです。ほとんどの場合、細かいケースをすべて理解することはできない、と彼らは主張します。これが、多くの複雑なフレームワークが 2 回または 3 回再試行する可能性があると考える理由ですが、最終的には最上位のフレームワーク レイヤーに RuntimeException をスローします。そこで、彼らはそこから何か有用なものを作成し (コンテキストを提供する意味のあるエラー)、すべての詳細をログに記録します。これは、ほとんどの場合、巨大なスタック トレースです。多くの開発者が恐れている知識の素晴らしいリソースです。

では、テストされていないコーナーケースの問題から回復できなかった場合はどうすればよいでしょうか? あなたが持っているすべてのコンテキストで注釈が付けられた最も意味のあるスタックトレースを(おそらくRuntimeExceptionのサブクラスで)スローします。監視を設定します。また、頻繁に問題が発生する場合は、修正してください。

于 2011-08-12T23:31:03.740 に答える
1

ServerSocketの仕様を読むと、「接続の待機中にI/Oエラーが発生した場合」にIOExceptionがスローされることがわかります。accept()再びソケットに接続しても安全ですか?はい。同じ例外が再度スローされますか?おそらくそうです。

于 2011-08-12T23:33:13.073 に答える
1

オブジェクトがまだ使用可能な状態にあるかどうかを確認する簡単な方法をまだ見つけていません。各オブジェクトは独自のルールを作成します。

ServerSocketの特定のケースでは、次の2つの異なる方法のいずれかを試します。

  • netstatまたはその他のユーティリティを実行して、OSがソケットの動作を認識していることを確認します。OSがリッスンしていると思わない場合は、何かが発生しています。また

  • 例外をスローするテストプログラムを作成し、それが何をするかを確認します。私はいつもこれを行っています(特にプロプライエタリソフトウェアで)。選択したServerSocketの場合は、考えられるすべてのシナリオ(たとえば、使用中のアドレス、不十分な特権など)によって、オブジェクトがまだ有効になることは決してないため、より困難になります。

于 2011-08-12T23:39:13.820 に答える
1

しかし、accept() がスローする可能性があるのは SocketTimeoutException だけではありません。他のすべての例外はどういう意味ですか?

javadocによると、宣言された例外はIOException、、、およびです。andは特定のコンテキストでのみ発生するため、キャッチして処理しようとしないでください。(回復したい問題ではありません!) 「その他の I/O エラー」が発生した場合に発生します。javadoc では、これらの I/O エラーが何であるかは特定されていませんが、次のような可能性があります。SecurityExceptionSocketTimeoutExceptionIllegalBlockingModeExceptionSecurityExceptionIllegalBlockingModeExceptionIOException

  • あなたがバインドしたアドレスはもはや有効ではありません
  • トランスポート プロトコル エラーが発生しました
  • OS プロトコル スタックで何らかのエラー (リソースの問題、バグなど) が発生しました

(javadoc がどのIOExceptionサブクラスがスローされる可能性があるかを述べていないという事実は、回復を試みるために巧妙なことをしようとするべきではないというヒントです。そうすると、コードはプラットフォームに依存する可能性があります。)

accept() への呼び出しを 2 つの catch 句でラップした場合: SocketTimeoutException と IOException の場合、IOException 句に入った後でも、関連する ServerSocket インスタンスを安全に使用できますか?

はいといいえ。アプリケーションを現在よりも悪い状態にしないという意味では安全です。一方で、次のaccept呼び出しが同じ問題で失敗しないという保証はありません。

IOExceptionアプリケーションが無人サーバーとして実行されることを意図している場合、問題が一時的なものであることを願って、ログに記録して再試行する以外に選択肢はないと思います。

于 2011-08-13T00:19:39.780 に答える
1

はい。オブジェクトはまだ存在します - エラー状態にある可能性があり、その場合、修正されるまで他の例外がスローされます。

于 2011-08-12T23:25:04.713 に答える
0

あなたはのjavadocへのあなたの答えを見つけることができますsetsoTimeout、それは言います:

指定されたタイムアウト(ミリ秒単位)でSO_TIMEOUTを有効/無効にします。このオプションをゼロ以外のタイムアウトに設定すると、このServerSocketに対するaccept()の呼び出しは、この時間だけブロックされます。タイムアウトが期限切れになると、ServerSocketはまだ有効ですが、java.net.SocketTimeoutExceptionが発生します。このオプションを有効にするには、ブロック操作を開始する前に有効にする必要があります。タイムアウトは0より大きい必要があります。ゼロのタイムアウトは無限のタイムアウトとして解釈されます。

于 2011-08-12T23:35:58.910 に答える