magazine.gif Java RMI

はじめに

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による通信

索引