RemoteException をチェック済みの例外にし、リモート メソッドに例外を throws 句にリストするよう要求するという決定は、宗教的なものではありません。この決定は、分散コンピューティングの信頼性を高める方法に基づいています。この質問は、私たちのユーザー リストに時々出てきます。少し前に投稿した詳細な回答があります。興味のある方はこちら。rmi-users アーカイブで見つけられなかったので、以下に含めました。
RemoteException を RuntimeException ではなく、checked Exception にする理由を説明したいと思います。
1) ネットワークが信頼できない
そうだといいのですが、実際にはそうではありません。どのネットワークにも一時的な障害があります。ネットワークの冗長性を組み込むことはできますが、実際には、ほとんどのネットワークにはそれがありません。イントラネットには、インターネットと同様に一時的な障害があります。そのため、作成されるすべての RPC は失敗する可能性があります。障害の種類は、「ネットワーク」自体とは何の関係もない場合があります。サーバーがファイル記述子を使い果たした場合、クライアントは接続例外を受け取ります。ネットワークが壊れているという意味では、これはネットワーク障害ではありません。サーバーがリソース不足の一時的な状態になっています。
RMI は、1 台のマシンがクラッシュしたときにネットワーク全体がクラッシュするという限られたケースのみを処理するようには設計されていません。このようなネットワークは、すべてが稼働しているか、すべてが停止しているかに関係なく、信頼できると見なされます。部分的な障害はありません。RMI は、より一般的なユーザーを対象としています。
2) クライアントから RPC の失敗を隠すことはできません
部分的な障害は、分散プログラミングの事実です。これらの障害は、プログラムに対して隠すことはできません。例外がチェックされているかチェックされていない例外であるかに関係なく、クライアントにエラーが表示されます。では、そのような失敗をクライアントにどのように示すべきでしょうか?
3) チェックされた例外は、より堅牢なプログラムを促進します
Oak と Java の初期バージョンにチェック例外がなかった時期がありました。例外処理は助言的なものであり、世の中は安全ではありませんでした。コンパイラによってチェックされる例外があることを推奨したのは、私たちのグループ (特に Jim Waldo と私 :-) でした。ジムは、ロバストなコードが支配する世界について語り、非常に説得力のある議論をしました。いくつかの検討の後、Java は例外をチェックするように改造されました。回復が行われなかった、またはアプリケーション エラーを反映した例外のみがチェックされません (たとえば、それぞれ OutOfMemoryError、NullPointerException)。そして、世界は再び安全になりました。
Java API とコンパイラの多くの例外がチェックされていないものからチェックされているものに変更され、コンパイラがその区別を強制し、実装のバグを発見したときの Java エンジニアの驚きを想像してみてください! そのため、エラー状態を処理するための最善の努力は、たとえ善意であったとしても、十分ではありませんでした。そのコンパイラは何かに役立ちます:-)
4) RemoteException はチェック済み例外でなければなりません
さて、ここで軌道に戻ります。RemoteException は RPC 呼び出しでは当たり前のことであり (#1、#2 を参照)、チェック済み例外は安全なコードを書かなければならない (#3) ため、RemoteException をチェック済み例外にするのは良い考えだと考えました。堅牢な分散プログラムを作成することは、例外を処理するのに役立つコンパイラがなければ十分に困難です。
そのため、RemoteException は OutOfMemoryError に似ていると主張する人もいるかもしれません。リモート呼び出しが失敗した場合、プログラムは停止するはずです。私はこの点に同意しません。はい、場合によっては、RemoteException から回復できないことがあります。しかし、信頼できる分散プログラムを作成している場合、クライアントは失敗をキャッチして適切に再試行する必要があります。おそらく、別のサーバーに接続するか、何らかのトランザクションを中止する必要があります。RemoteException が処理されない場合、浸透してクライアント (yuk) をクラッシュさせます。
他の人は、ローカルの場合とリモートの場合の両方で使用されるいくつかのリモート インターフェイスがあり、クライアントはローカルの場合の例外を処理する必要がないため、RemoteException を throws 句に含めて処理する必要はないと述べています。必須ではありません。ここで、リモート インターフェイス メソッドが RemoteException を省略できるようにし、未チェックの RemoteException をスローするスタブを生成する「rmic」スイッチがある場合、クライアントには何もありません。
問題の選択。例外処理の決定はクライアントに委ねるべきです。チェックされていない例外のみをスローするインターフェイスを定義すると、それらの例外を処理するためにコンパイラの助けが必要なクライアントを作成することはできません。上記の例から、チェックされた例外が堅牢なコードを促進することをすでに見てきました。
時々発生するもう 1 つの問題は、開発者が単純にローカル インターフェイスを変換し、それらをリモート インターフェイスとして使用する必要があることです。これは少数のケースでは機能する可能性がありますが、インターフェイスが同時実行性、部分的な障害、および呼び出しの遅延を考慮して設計されていない場合、インターフェイスによってキャプチャされたプロトコルは分散ケースでの使用に適していない可能性があります。操作を冪等にするのに十分な情報がこれらの操作で渡されますか? おそらく、しかしほとんどの場合そうではありません。
すべての throws 節に RemoteException を入れるのは面倒に思えるかもしれませんが、堅牢な分散アプリケーションを作成するために支払う代償です。
-- アン・ウォルラス