Java RMI
オライリー・ジャパン
著者:William Grosso
訳者:田和勝
はじめに
I部 RMIアプリケーションの基礎:設計と実装
1章 ストリーム
1.1 中心となるクラスたち
1.1.1 InputStream
1.1.2 IOException
1.1.3 OutputStream
1.2 ファイルの中身を表示する
1.3 ストリームを階層化する
1.3.1 ファイルの圧縮
1.3.2 便利な中間ストリーム
1.4 リーダーとライター
1.4.1 ViewFileアプリケーションの改良
2章 ソケット
2.1 インターネットの定義
2.2 ソケット
2.2.1 ソケットの作成
2.2.2 プロトコルとメタデータ
2.3 ServerSocket
2.3.1 accept( )メソッド
2.3.2 簡単なWebサーバ
2.4 ソケットのカスタマイズ
2.5 特殊用途のソケット
2.5.1 ストリームを直接操作する
2.5.2 もっと良い方法:ソケットをサブクラス化する
2.5.3 特殊用途のソケット
2.5.4 ファクトリ
2.5.5 ソケットファクトリ
2.5.6 セキュリティ
2.6 SSLを使用する
2.6.1 SSLハンドシェーク
2.6.2 JSSE(JavaによるSSLの実装)を使用する
2.6.3 前出のWebサーバの改良
3章 ソケットベースのプリンタサーバ
3.1 ネットワークベースのプリンタ
3.2 基本オブジェクト
3.3 プロトコル
3.3.1 オブジェクトのカプセル化と送信
3.3.2 ネットワーク対応のラッパーオブジェクト
3.4 アプリケーションのメイン部
3.4.1 クライアントを書く
3.4.2 アーキテクチャ図の描き直し
3.5 改良点
3.5.1 これらの改良を施すと
4章 RMIベースのプリントサーバ
4.1 RMIの基本構造
4.1.1 ネットワーク越しのメソッド呼び出し
4.1.2 「値渡し」と「参照渡し」
4.2 アーキテクチャ図の描き直し
4.3 基本オブジェクトの実装
4.3.1 Printerインタフェース
4.3.2 プリンタの実装
4.3.3 データオブジェクト
4.4 サーバの残りの部分
4.5 クライアントアプリケーション
4.6 まとめ
5章 分散アプリケーションの具体例:バンキングアプリケーションの導入
5.1 分散アプリケーションの具体例:バンキングシステム
5.2 アーキテクチャのラフスケッチ
5.2.1 ラフスケッチの5つの手順
5.3 基本的な利用パターン
5.4 その他の設計上の考慮点
5.4.1 後回しにすること
5.4.2 環境による制約
5.5 バンキングアプリケーションの分散アーキテクチャ
5.6 分散アプリケーションで発生する問題
5.6.1 部分的障害
5.6.2 ネットワークレイテンシ
6章 リモートサーバに関する決定事項
6.1 ちょっとした偏向
6.2 サーバ設計時の着眼点
6.2.1 各サーバのインスタンスは貴重な(限りのある)共有リソースを必要とするか
6.2.2 サーバを複数のマシンにうまく複製/拡張できるか
6.2.3 単一サーバで典型的なクライアントとのやり取りを処理できるか
6.2.4 サーバに複数のクライアントを同時に処理させることが容易にできるか
6.2.5 コードが正しいかどうかを簡単に判断できるか
6.2.6 サーバの障害はどれくらい破壊的か
6.2.7 ソフトウェアの機能拡張と新機能の追加は容易か
6.3 BankオプションとAccountオプションのどちらを実装すべきか
7章 リモートインタフェースの設計
7.1 リモートインタフェース設計時の重要事項
7.1.1 メソッドオブジェクトを渡すべきか
7.1.2 引数としてオブジェクトとプリミティブ値のどちらを渡すべきか
7.1.3 戻り値としてオブジェクトかプリミティブ値のどちらを受信すべきか
7.1.4 個々のメソッド呼び出しは帯域幅を浪費するか
7.1.5 1つの概念的な操作が1つのメソッド呼び出しに対応しているか
7.1.6 インタフェースは正しい量のメタデータを公開しているか
7.1.7 適切な分散例外のセットが特定されているか
7.2 データオブジェクトの構築
7.2.1 データオブジェクトはふつう機能メソッドを持たない
7.2.2 インタフェースはデータオブジェクトを提供する
7.3 部分的障害の対策
8章 バンキングサーバの実装
8.1 サーバの構造
8.2 サーバの実装
8.2.1 UnicastRemoteObjectを拡張したサーバ
8.2.2 UnicastRemoteObjectを拡張しないサーバ
8.2.3 UnicastRemoteObjectを拡張する
8.3 スタブとスケルトンの生成
8.3.1 スケルトンの数を減らす(スケルトンなしで済ます)
9章 アプリケーションの残りの部分
9.1 起動用コードに必要なもの
9.1.1 サーバのライフサイクルという考え方
9.2 実際の起動用コード
9.3 テストアプリケーションの構築
9.4 クライアントアプリケーションの構築
9.4.1 サーバへのコネクションを保持したままにしない
9.4.2 引数の妥当性チェックをできるかぎりクライアント側で行う
9.4.3 実際のクライアントアプリケーション
9.5 アプリケーションの配置
II部 スケーラビリティの実現
10章 直列化
10.1 直列化はなぜ必要か
10.1.1 オブジェクト生成をさらに堀り下げてみると
10.2 直列化の利用
10.2.1 ObjectOutputStream
10.2.2 ObjectInputStream
10.3 クラスを直列化可能にする方法
10.3.1 Serializableインタフェースを実装する
10.3.2 インスタンスレベルでローカルに定義された状態が正しく直列化されることを確認する
10.3.3 スーパークラスの状態が正しく直列化されることを確認する
10.3.4 equals( )とhashCode( )を必要に応じてオーバーライドする
10.3.5 DocumentDescriptionを直列化可能にする
10.4 直列化アルゴリズム
10.4.1 データフォーマット
10.4.2 簡易バージョンの直列化アルゴリズム
10.4.3 RMI向けにカスタマイズされた直列化アルゴリズム
10.4.4 ダイレクトコネクションの保守
10.5 クラスのバージョン管理
10.5.1 バージョン管理に関する2つの問題
10.5.2 クラスの変更を直列化メカニズムが検出する方法
10.5.3 バージョン管理機構を自前で実装する
10.6 直列化が抱えるパフォーマンス上の問題
10.6.1 リフレクションに依存している
10.6.2 データフォーマットが冗長である
10.6.3 必要以上に簡単にデータを送信してしまう
10.7 Externalizableインタフェース
10.7.1 ExternalizableとSerializableの比較
10.7.2 最後の注意点
11章 スレッド
11.1 複数のクライアント
11.2 基本的な用語
11.2.1 コールスタック
11.2.2 ヒープ
11.2.3 スレッド
11.2.4 ミューテックス
11.2.5 プリンタサーバのスレッド化
11.3 スレッド化の概念
11.3.1 個々のスレッドを制御する
11.3.2 スレッドの動作を調整する
11.3.3 キャッシュ管理
11.3.4 スレッドに優先度を割り当てる
11.4 Javaのスレッド機能
11.4.1 ミューテックス変数が関連付けられたオブジェクト
11.4.2 Objectクラスに定義されたスレッド操作用メソッド
11.4.3 クラス
11.5 デッドロック
11.6 スレッド化とRMI
12章 スレッド化の実装
12.1 基本的なこと
12.2 スレッド化にあたっての指針
12.2.1 実際に動くコードから始める
12.2.2 一番重要なのはデータの整合性
12.2.3 同期化ブロックの実行所要時間を最小化する
12.2.4 コンテナクラスを使用するときの注意点
12.2.5 コンテナをスレッド間通信の仲介役として使用する
12.2.6 不変オブジェクトはそのままでもスレッドセーフ
12.2.7 スレッドはいつも安全に停止すること
12.2.8 バックグランドスレッドの優先順位は低くする
12.2.9 何を直列化するのかに注意する
12.2.10 スレッド化を用いて応答時間のゆれを小さくする
12.2.11 スレッドが参照するオブジェクトの数を制限する
12.2.12 同じ順番でロックを獲得する
12.2.13 作業スレッドを用いてデッドロックを防ぐ
12.3 スレッドプールを用いた拡張
12.3.1 プールという考え方
12.3.2 プールを定義する2つのインタフェース
12.3.3 プールメカニズム:最初の実装
12.3.4 SimplePoolの問題点
12.3.5 オブジェクト生成用スレッド
12.3.6 オブジェクト返却用スレッドの追加
12.3.7 プールを徐々に縮小する
12.3.8 さらなる2つの注意点
12.4 最後に
13章 分散アプリケーションのテスト
13.1 バンキングアプリケーションのテスト
13.1.1 何をテストするか
13.1.2 サーバのテスト方法
13.1.3 バンキングアプリケーションのテスト
14章 RMIレジストリ
14.1 なぜネーミングサービスを使用するのか?
14.1.1 ブートストラップ
14.1.2 ネーミングサービスはどのようなとき便利か?
14.2 RMIレジストリ
14.2.1 bind( )、rebind( )、unbind( )
14.2.2 lookup( )とlist( )
14.3 RMIレジストリはRMIサーバである
14.3.1 レジストリのブートストラップ
14.4 Registryの中身
14.4.1 レジストリに問い合わせる
14.4.2 アプリケーション固有のレジストリを起動する
14.5 RMIレジストリの制限
14.5.1 ディレクトリとエントリ
14.6 セキュリティの問題
15章 ネーミングサービス
15.1 基本的な設計、用語、要件
15.1.1 階層化
15.1.2 属性による問い合わせ
15.2 我々が実装するネーミングサービスの要件
15.2.1 利用パターン
15.3 フェデレーションとスレッド化
15.3.1 フェデレーション(連合)
15.4 Contextインタフェース
15.4.1 セットとリストを表す値オブジェクト
15.4.2 パス、サーバ名、属性はまったく別物
15.4.3 ヌル引数でもOK
15.4.4 属性は単一値とする
15.4.5 コンテキスト処理用のメソッドは別に用意する
15.4.6 コンテキストとしてバインドされたコンテキストは属性を持たない
15.4.7 コンテキストはサブコンテキストを直接作成できる
15.4.8 Remoteイテレータは用意しない
15.5 値オブジェクト
15.5.1 AttributeSet
15.5.2 PathとContextList
15.6 ContextImpl
15.6.1 NameAttributeSetPair
15.6.2 RemoteHolder
15.6.3 ContextHolder
15.6.4 ContextImpl
15.6.5 ブートストラップ
15.6.6 バージョン2.0
15.7 ネーミングサービスの切り替え
15.7.1 バンキングアプリケーションを変更する
15.8 Java Naming and Directory Interface(JNDI)
15.8.1 Contextインタフェース
15.8.2 JNDIをバンキングアプリケーションで使用する
16章 RMIランタイム
16.1 リモートメソッド呼び出しの仕組みの復習
16.1.1 RMIがブートストラップ問題を解決する方法
16.2 分散ガベージコレクション
16.2.1 通常のガベージコレクション
16.2.2 ネットワークガベージの定義
16.2.3 リース
16.2.4 実際の分散ガベージコレクタ
16.2.5 Unreferencedインタフェース
16.3 RMIのロギング機能
16.3.1 標準ログ
16.3.2 専用ログ
16.3.3 デバッグ用ログ
16.4 その他のJVMパラメータ
16.4.1 Java基本パラメータ
16.4.2 RMI基本パラメータ
16.4.3 トランスポート層パラメータ
16.4.4 分散ガベージコレクタ関連のパラメータ
17章 ファクトリとアクティベーションフレームワーク
17.1 リソース管理
17.2 ファクトリ
17.2.1 基本設計の見直し
17.3 汎用ファクトリの実装
17.3.1 基本ファクトリ
17.3.2 既存アプリケーションの修正
17.4 ファクトリの改良
17.4.1 これまでの実装方法
17.4.2 口座ロック機構の構築
17.5 永続性とサーバのライフサイクル
17.6 アクティベーション
17.6.1 アクティベーションを使うために必要なコード変更
17.6.2 起動可能なシステムの配置
17.6.3 ActivationDesc、ActivationGroupDesc、ActivationGroupの詳細
17.6.4 起動可能なサーバのシャットダウン
17.6.5 rmidのコマンドライン引数
17.6.6 アクティベーションパラメータ
17.7 最後に
III部 より高度なトピック
18章 カスタムソケットの利用
18.1 カスタムソケットファクトリ
18.1.1 カスタムソケットファクトリの生成
18.2 カスタムソケットのアプリケーションへの組み込み
18.2.1 通常のサーバの修正
18.2.2 起動可能なサーバの修正
18.2.3 デフォルトのサーバの変更
18.2.4 パラメータとの関連
19章 動的なクラスローディング
19.1 アプリケーション配置の難しさ
19.2 クラスローダ
19.2.1 クラスがロードされる仕組み
19.3 動的クラスローディングの動作原理
19.3.1 再配置するケース
19.3.2 複数バージョンを並列配置するケース
19.4 クラスサーバ
19.4.1 クラスを要求する
19.4.2 クラスを受信する
19.4.3 JARファイルを処理する
19.4.4 Sunのクラスサーバ
19.5 動的クラスローディングをアプリケーションで使う
19.5.1 サーバ側の変更
19.5.2 ネーミングサービスの変更
19.5.3 クライアント側の変更
19.5.4 動的クラスローディングを完全に無効にする
20章 セキュリティポリシー
20.1 新たなセキュリティ上の問題
20.2 アクセス権
20.2.1 アクセス権の種類
20.3 セキュリティマネージャ
20.3.1 SecurityManagerのインストール
20.3.2 セキュリティマネージャの動作原理
20.3.3 java.security.debug
20.4 セキュリティポリシーの設定
20.4.1 3つのポリシーファイル
20.4.2 ポリシーファイルの中身
20.4.3 RMIでのセキュリティポリシーの使用
20.4.4 ポリシーツール
20.4.5 終わりに
21章 マルチスレッドクライアント
21.1 異なる種類のリモートメソッド
21.1.1 プリンタ型メソッド
21.1.2 レポート型メソッド
21.2 プリンタ型メソッドの処理
21.2.1 最初の解決策
21.2.2 より良い解決策
21.3 レポート型メソッドの処理
21.3.1 7章再考
21.3.2 クライアント側のバックグラウンドダウンロードの実装
21.4 以上のサンプルコードを一般化すると
22章 HTTPトンネリング
22.1 ファイアウォール
22.2 CGIと動的コンテンツ
22.2.1 CGI
22.2.2 サーブレット
22.3 HTTPトンネリング
22.3.1 RMIがメッセージをトンネリングする仕組み
22.4 HTTPトンネリング用サーブレットの実装
22.4.1 サーブレットのコード
22.5 トンネリングの動作を変更する
22.6 HTTPトンネリングを使用したバンキングアプリケーション
22.7 HTTPトンネリングの欠点
22.8 HTTPトンネリングを無効にする
23章 RMI、CORBA、RMI/IIOP
23.1 CORBAの動作原理
23.1.1 その他の構成要素
23.2 バンキングアプリケーションをCORBAで実装する
23.2.1 インタフェースの定義
23.2.2 スタブとスケルトンの生成
23.2.3 サーバ
23.2.4 起動用コードとクライアントコード
23.3 CORBAとRMIの簡単な比較
23.4 CORBA上のRMI
23.4.1 RMI/IIOPの欠点
23.5 バンキングアプリケーションをRMI/IIOP対応にする
23.5.1 CORBAによる通信
索引