本発明は、ユーザーセッション間の分離(isolation)を提供し、データを共有するための技術を実施するコンピュータプログラムプロダクトを含む方法及び装置を提供する。
一般的な一態様において、本技術は、データ処理装置に、第1のランタイムクラスのインスタンス(instance)である第1のデータオブジェクトの識別(identification)を受信させ、前記第1のランタイムクラスが共有可能であるかどうかを判定させ、前記第1のデータオブジェクトが1又は2以上の参照データオブジェクトを参照するかどうかを判定させるように操作可能なコンピュータプログラムプロダクトを特徴とする。もし、前記第1のデータオブジェクトが1又は2以上の参照データオブジェクトを参照すれば、前記コンピュータプログラムプロダクトは、さらに、前記データ処理装置に、前記1又は2以上の参照データオブジェクトをトラバース(traverse)させ、そして、トラバースされた各データオブジェクトについて、前記トラバースされたデータオブジェクトがインスタンスであるところのランタイムクラスが共有可能であるかどうかを判定させるように操作可能である。
有利な実施例は、以下の1又は2以上の特徴を含むことができる。前記1又は2以上の参照データオブジェクトをトラバースするステップは、前記1又は2以上の参照データオブジェクトの推移的クロージャ(transitive closure)における各データオブジェクトを再帰的にトラバースするステップを含むことができる。
もし、前記第1のランタイムクラスが共有可能であり、且つトラバースされた各データオブジェクトの前記ランタイムクラスが共有可能であれば、前記第1のデータオブジェクト及びトラバースされた各データオブジェクトは、オブジェクトグループにグループ化され、且つ、前記オブジェクトグループは、共有メモリ領域にコピーされることができる。
もし、前記第1のランタイムクラスが共有可能でなければ、または、少なくとも一つのトラバースされたデータオブジェクトの前記ランタイムクラスが共有可能でなければ、消極的ステータスの指示(indication)が生成される。
前記第1のランタイムクラスが共有可能であるかどうかを判定するステップは、前記第1のランタイムクラスが共有可能であることが前もって宣言されているかどうかを判定するステップを含むことができる。
前記第1のランタイムクラスは、1又は2以上のベースクラス(base class)から得ることができ、且つ1又は2以上のフィールド(field)を含むことができる。前記第1のランタイムクラスが共有可能であるかどうかを判定するステップは、前記第1のランタイムクラスが直列化インターフェイス(serialization interface)を実施するかどうかを判定するステップと、前記第1のランタイムクラスのオブジェクトインスタンスの直列化又は非直列化(deserialization)の期間にカスタムコードが実行されるかどうかを判定するステップと、全ての前記ベースクラスが直列化可能であるかどうかを判定するステップと、全ての前記フィールドが直列化されるかどうかを判定するステップと、前記第1のランタイムクラスの前記オブジェクトインスタンスがガーベッジコレクション(garbage collection)に影響を与えるかどうかを判定するステップとを含むことができる。
前記第1のランタイムクラスは、Java(登録商標)クラスであってもよく、前記直列化インターフェイスは、java(登録商標).io.Serializableであってもよい。
カスタムコードが実行されるかどうかを判定するステップは、前記第1のランタイムクラスが所定組のメソッドの中のメソッドを含んでいるかどうかを判定するステップを含むことができる。前記所定組のメソッドは、readObject( ),writeObject( ),readExternal( ),writeExternal( ),readResolve( ),writeReplace( )メソッドを含むことができる。
全ての前記ベースクラスが直列化可能であるかどうかを判定するステップは、前記ベースクラスの中の各クラスが前記直列化インターフェイスを実施するかどうかを判定するテップと、もし、前記ベースクラスの中のクラスが前記直列化インターフェイスを実施しなければ、前記クラスが普通のデフォルトのコンストラクター(constructor)を含むかどうかを判定するステップとを含むことができる。
全ての前記フィールドが直列化されるかどうかを判定するステップは、前記フィールドの何れもトランジェントフィールド(transient field)であるかどうかを判定するステップを含むことができる。また、全ての前記シールドが直列化されるかどうかを判定するステップは、前記フィールドの何れもserialPersistentFieldであるかどうかを判定するステップを含むこともできる。
前記第1のランタイムクラスのオブジェクトインスタンスがガーベッジコレクションに影響を与えるかどうかを判定するステップは、前記第1のランタイムクラスが普通の終了化子(finalizer)を含むかどうかを判定するステップを含むことができる。前記第1のランタイムクラスがJava(登録商標)クラスであれば、前記第1のランタイムクラスのオブジェクトインスタンスがガーベッジコレクションに影響を与えるかどうかを判定するステップは、また、前記第1のランタイムクラスがjava(登録商標).lang.ref.Referenceクラスから得られるかどうかを判定するステップを含むことができる。
前記第1のランタイムクラスが共有可能であるかどうかを判定するステップは、前記ランタイムクラスのランタイム表現が共有可能であるかどうかを判定するステップと、前記第1のランタイムクラスのためのクラスローダー(class loader)が共有可能であるかどうかを判定するステップとを更に含むことができる。
前記第1のランタイムクラスの前記ランタイム表現が共有可能かどうかを判定するステップは、前記ランタイム表現が第1の所定の場所に格納されるかどうかを判定するステップを含むことができる。前記第1のランタイムクラスのための前記クラスローダーが共有可能かどうかを判定するステップは、前記クラスローダーが第2の所定の場所に格納されているかどうかを判定するステップを含むことができる。
他の態様において、本技術は、データ処理装置に、ゼロ又はそれ以上の参照データオブジェクトを参照する第1のデータオブジェクトであって第1のランタイムシステムにおける該第1のデータオブジェクトの識別を受信させ、前記参照データオブジェクトの推移的クロージャ(transitive closure)及び前記第1のデータオブジェクトから構成されるデータオブジェクトの共有クロージャ(shared closure)を識別させ、前記データオブジェクトの共有クロージャが第2のランタイムシステムにおいて使用可能かどうかを判定させるように操作可能なコンピュータプログラムプロダクトを特徴とする。
有利な実施例は、次の1又は2以上の特徴を含むことができる。前記第1及び第2のランタイムシステムは、Java(登録商標)仮想マシン又は共通言語仮想マシン(Common Language Runtime virtual machine)を含む仮想マシンであってもよい。前記データオブジェクトの共有クロージャは、ユーザーコンテキスト情報(user context information)を含むことができる。
前記共有クロージャが前記第2のランタイムシステムにおいて使用可能であるかどうかを判定するステップは、前記データオブジェクトの共有クロージャにおける各データオブジェクトがカスタムコードを実行することなく直列化可能であるかどうかを判定するステップを含むことができる。
前記共有クロージャが前記第2のランタイムシステムにおいて使用可能であるかどうかを判定するステップは、前記共有クロージャにおける各データオブジェクトのランタイムクラスが共有可能であるかどうかを判定するステップを含むことができる。
各データオブジェクトがインスタンスであるところのランタイムクラスは、1又は2以上のベースクラスから得ることができ、1又は2以上のフィールドを有することができ、且つ、前記ランタイムクラスが共有可能であるかどうかを判定するステップは、前記ランタイムクラスが直列化インターフェイスを実施するかどうかを判定するステップと、前記ランタイムクラスのオブジェクトインスタンスの直列化又は非直列化の期間中にカスタムコードが実行されるかどうかを判定するステップと、全ての前記ベースクラスが直列化可能であるかどうかを判定するステップと、全ての前記フィールドが直列化されるかどうかを判定するステップと、前記ランタイムクラスのオブジェクトインスタンスがガーベッジコレクションに影響を与えるかどうかを判定するステップとを含むことができる。
消極的ステータス指示(negative status indication)は、前記データオブジェクトの共有クロージャが前記第2のランタイムシステムにおいて使用可能でなければ、生成されることができる。
前記データオブジェクトの共有クロージャは、共有メモリ領域にコピーされることができる。前記コンピュータプログラムプロダクトは、更に、前記データ処理装置に、前記データオブジェクトの前記共有クロージャの前のバージョンが前記共有メモリ領域に存在するかどうかを判定させ、且つ、バージョンナンバーを前記データオブジェクトの共有クロージャと関連づけさせるように操作可能であってもよい。
他の態様において、本技術は、データ処理装置に、識別子を受信させ、前記識別子と関連する共有クロージャを識別させ、前記共有クロージャをランタイムシステムと関連づけさせるように操作可能なコンピュータプログラムプロダクトを特徴とする。前記共有クロージャは、共有メモリ領域に配置され、且つ、第1のデータオブジェクトと該第1のデータオブジェクトによって参照されるデータオブジェクトの推移的クロージャから構成される。
有利な実施例は、1又は2以上の次の特徴を含むことができる。前記ランタイムシステムは、Java(登録商標)仮想マシン又は共通言語ランタイム仮想マシンであってもよい。前記共有クロージャを識別するステップは、前記共有クロージャの現在のバージョンを識別するステップを含むことができる。
前記共有クロージャは、前記ランタイムシステムと関連するアドレス空間に前記共有クロージャをコピー又はマッピングすることにより、前記ラインタイムシステムと関連づけられることができる。前記共有クロージャが前記ランタイムシステムと関連するアドレス空間にマッピングされた場合、前記共有クロージャを前記ランタイムシステムに関連づけるステップは、前記共有クロージャに対するライトアクセスを阻止し、または、前記共有クロージャにおけるデータオブジェクトに対する第1のライトアクセスを検出すると、すぐに、前記ラインタイムシステムと関連する前記アドレス空間に前記共有クロージャをコピーするステップを更に含むことができる。
共有クロージャは、削除されたものとしてマークされることができる。削除されたものとして共有クロージャをマークするステップは、前記共有クロージャが追加的ランタイムシステムと関連づけられることを防ぐステップを含むことができる。
他の態様において、本技術は、データ処理装置に、一組のデータオブジェクトを識別させるように操作可能なコンピュータプログラムプロダクトを特徴とし、前記一組のデータオブジェクトの中の各データオブジェクトは、第1のランタイムシステムにおける前記データオブジェクトに関するランタイムメタデータに対する参照を有する。前記コンピュータプログラムプロダクトは、更に、前記データ処理装置に、各データオブジェクトにおける前記ランタイムメタデータに対する前記参照をプロキシで置き換えさせ、そして、前記一組のデータオブジェクトを第2のランタイムシステムに伝送させるように操作可能である。
有利な実施例は、1又は2以上の次の特徴を含むことができる。前記一組のデータオブジェクトの中の各データオブジェクトについて、前記データオブジェクトに関する前記ランタイムメタデータに対する参照は、前記データオブジェクトがインスタンスであるところのクラスのランタイム表現に対する参照を含むことができる。
前記第1のランタイムシステムは、第1の仮想マシンを含むことができ、前記第2のランタイムシステムは、第2の仮想マシンを含むことができる。前記第1及び第2の仮想マシンは、Java(登録商標)仮想マシン又は共通言語ランタイム仮想マシンであることができる。前記第1のランタイムシステムは、第1の物理マシン上に配置されることができ、前記第2のランタイムシステムは、第2の異なる物理マシン上に配置されることができる。
前記一組のデータオブジェクトを識別するステップは、1又は2以上の参照データオブジェクトの推移的クロージャを識別するステップを含むことができ、各参照データオブジェクトは、第1のデータオブジェクトによって参照されるオブジェクトである。
他の態様において、本技術は、データ処理装置に、各データオブジェクトがプロキシを含んでなる一組のデータオブジェクトを第1のランタイムシステムから受信させ、前記一組のデータオブジェクトを第2のランタイムシステムにコピーさせ、前記一組のデータオブジェクトにおける各データオブジェクトについて、前記データオブジェクトに関するランタイムメタデータを識別させて、前記データオブジェクトにおけるプロキシを前記データオブジェクトに関する前記ランタイムメタデータに対する参照で置き換えさせるように操作可能なコンピュータプログラムプロダクトを特徴とする。
有利な実施例は、1又は2以上の次の特徴を含むことができる。前記コンピュータプログラムプロダクトは、更に、前記各データオブジェクトに関するランタイムメタデータが前記第2のランタイムシステムにおいて利用可能であるかを判定させ、そのランタイムメタデータが前記第2のランタイムシステムにおいて利用可能でなければ、前記第2のランタイムシステムにおける各データオブジェクトに関する前記ランタイムメタデータをインストールさせるように操作可能であってもよい。
各データオブジェクトについて、前記データオブジェクトに関するランタイムメタデータに対する参照は、前記データオブジェクトがインスタンスであるところのクラスのランタイム表現に対する参照を含むことができる。前記コンピュータプログラムプロダクトは、更に、各オブジェクトインスタンスの前記クラスのランタイム表現が前記第2のランタイムシステムにおいて利用可能であるかを判定させ、そのランタイム表現が前記第2のランタイムシステムにおいて利用可能でなければ、前記第2のランタイムシステムにおける各オブジェクトインスタンスの前記クラスのランタイム表現をインストールさせるように操作可能であってもよい。
前記第1のランタイムシステムは、第1の仮想マシンを含むことができ、前記第2のランタイムシステムは、第2の仮想マシンを含むことができる。前記第1及び第2の仮想マシンは、Java(登録商標)仮想マシン又は共通言語ランタイム仮想マシンであってもよい。前記第1のランタイムシステムは、第1の物理マシン上に配置されることができ、前記第2のランタイムシステムは、第2の異なる物理マシン上に配置されることができる。
前記一組のデータオブジェクトは、1又は2以上の参照データオブジェクトの推移的クロージャと第1のデータオブジェクトから構成され、各参照データオブジェクトは前記第1のデータオブジェクトによって参照されるオブジェクトである。
前記ランタイムメタデータを識別して前記一組のデータオブジェクトの中の各データオブジェクトにおける前記プロキシを置き換えるためのオペレーションは、前記一組のデータオブジェクトが受信された後、実質的に即座に発生することができる。或いは、それらのオペレーションは、各データオブジェクトが前記第2のランタイムシステムにおいてアクセスされるときに発生することができる。
他の態様において、本技術は、データ処理装置に、ユーザーセッションのためにランタイムシステムを初期化させ、共有メモリ領域におけるデータオブジェクトの共有クロージャを生成させ、前記ユーザーセッションに対応するリクエストを受信させ、一組のオペレーションシステム処理の中から第1の処理を選択させ、前記ランタイムシステムを前記第1の処理にバインド(bind)させ、前記データオブジェクトの共有クロージャを前記ランタイムシステムに関連づけさせるように操作可能なコンピュータプログラムプロダクトを特徴とする。前記データオブジェクトの共有クロージャは、1又は2以上の参照データオブジェクトの推移的クロージャと第1のデータオブジェクトから構成され、各参照データオブジェクトは、前記第1のデータオブジェクトによって参照される。
有利な実施例は、1又は2以上の次の特徴を含むことができる。前記ランタイムシステムは、仮想マシンを含むことができる。前記仮想マシンは、Java(登録商標)仮想マシン又は共通言語ランタイム仮想マシンであることができる。
前記データオブジェクトの共有クロージャは、前記ユーザーセッションに対応するユーザーコンテキスト情報を含むことができる。
前記共有クロージャを前記ランタイムシステムと関連づけるステップは、前記共有クロージャを前記第1の処理にバインドするステップを含むことができる。前記共有クロージャを前記第1の処理にバインドするステップは、前記共有クロージャを前記第1の処理の前記アドレス空間にコピー又はマッピングするステップを含むことができる。もし、前記共有クロージャが前記第1の処理のアドレス空間にマッピングされれば、前記共有クロージャをバインドするステップは、更に、前記共有クロージャに対するライトアクセスを阻止し、または、前記共有クロージャにおける前記データオブジェクトの一つに対する第1のライトアクセスを検出したときに、すぐに、前記共有クロージャを前記第1の処理のアドレス空間にコピーするステップを含むことができる。
前記コンピュータプログラムプロダクトは、更に、前記データ処理装置に、第2のユーザーセッションのために第2のランタイムシステムを初期化させ、前記第2のユーザーセッションに対応する第2のリクエストを受信させ、前記一組のオペレーティングシステム処理の中から第2の処理を選択させ、前記第2のランタイムシステムを前記第2の処理にバインドさせ、前記データオブジェクトの共有クロージャを前記第2のランタイムシステムに関連づけさせるように操作可能であってもよい。
他の態様において、本技術は、データ処理装置に、共有メモリ領域にユーザーセッションに対応するユーザーコンテキストを格納させ、前記ユーザーセッションに対応するリクエストを受信させ、一組のオペレーションシステム処理の中からアドレス空間を有する処理を選択させ、一組のランタイムシステムの中から一つのランタイムシステムを選択させ、前記ランタイムシステムを前記処理にバインドさせ、前記ユーザーコンテキストを前記ランタイムシステムに関連づけさせるように操作可能なコンピュータプログラムプロダクトを特徴とする。
有利な実施例は、1又は2以上の次の特徴を含むことができる。前記一組のランタイムシステムにおける各ランタイムシステムは、仮想マシンを含むことができる。仮想マシンは、Java(登録商標)仮想マシン又は共通言語ランタイム仮想マシンであることができる。
前記ユーザーコンテキストは、第1のデータオブジェクトと該第1のデータオブジェクトによって参照されるデータオブジェクトの前記推移的クロージャから構成される共有クロージャを含むことができる。
前記ランタイムシステムは、前記共有メモリ領域に格納されることができ、前記ランタイムシステムを前記処理にバインドするステップは、前記ランタイムシステムに対応する前記共有メモリ領域の一部を前記処理のアドレス空間にマッピングするステップを含むことができる。
前記ユーザーコンテキストを前記ランタイムシステムに関連づけるステップは、前記ユーザーコンテキストを前記処理にバインドするステップを含むことができる。前記ユーザーコンテキストを前記処理にバインドするステップは、前記ユーザーコンテキストを前記処理のアドレス空間にコピー又はマッピングするステップを含むことができる。もし、前記ユーザーコンテキストが前記処理のアドレス空間にマッピングされれば、前記ユーザーコンテキストをバインドするステップは、前記ユーザーコンテキストに対する第1のライトアクセスを検出したときに、すぐに、前記ユーザーコンテキストを前記処理のアドレス空間にコピーするステップを更に含むことができる。
前記コンピュータプログラムプロダクトは、前記データ処理装置に、前記ユーザーコンテキストを前記処理からバインド解除(unbind)させるように更に操作可能であってもよい。前記ユーザーコンテキストを前記処理からバインド解除するステップは、前記ユーザーコンテキストを前記共有メモリ領域にコピーするステップを含むことができる。前記ユーザーコンテキストを前記処理からからバインド解除するステップは、前記ユーザーコンテキストの前のバージョンが前記共有メモリ領域に存在するかを判定し、前記ユーザーコンテキストの前のバージョンが存在すれば、前記共有メモリ領域に前記ユーザーコンテキストの新たなバージョンを生成するステップを更に含むことができる。
前記処理がブロックされたことを検出すると、すぐに、前記ランタイムシステムと前記ユーザーコンテキストの双方は、前記処理からバインド解除されることができる。前記処理がブロックされたことを検出するステップは、前記処理が、入力/出力(I/O)イベントが完了されたことを待っていることを検出するステップを含むことができる。I/Oイベントが完了されたことを検出すると、すぐに、利用可能な処理が前記一組のオペレーティングシステム処理の中から選択されることができ、そして前記ランタイムシステム及び前記ユーザーコンテキストは、前記利用可能な処理にバインドされることができる。
前記コンピュータプログラムプロダクトは、前記データ処理装置に、前記ランタイムシステムを前記処理からバインド解除させるように更に操作可能であってもよい。
前記一組のオペレーティングシステム処理は、2又はそれ以上の物理マシンに分散されることができ、そして、前記処理は、前記2又はそれ以上の物理マシンの中の第1のマシン上で実行されることができる。前記ユーザーコンテキストは、プロキシを備えた第1のデータオブジェクトを含むことができる。前記ユーザーコンテキストを前記ランタイムシステムに関連づけるステップは、前記プロキシを、前記第1のデータオブジェクトに関するランタイムメタデータに対する参照で置き換えるステップを含むことができ、前記ランタイムメタデータは、前記第1のマシンに格納される。
他の態様において、本技術は、一組の処理と、一組のランタイムシステムと、複数のユーザーコンテキストを格納するための共有メモリ領域と、配信コンポーネント(dispatcher component)を備えるコンピュータサーバーを特徴とする。前記配信コンポーネントは、前記複数のユーザーコンテキストにおけるユーザーコンテキストに対応するリクエストを受信し、前記一組の処理の中から利用可能な処理を選択し、前記一組のランタイムシステムの中から利用可能なランタイムシステムを選択し、前記利用可能なランタイムシステムと前記ユーザーコンテキストの識別を、前記リクエストの処理のための前記利用可能な処理に伝送するように操作可能である。
有利な実施例は、1又は2以上の次の特徴を含むことができる。前記一組のランタイムシステムにおける各ランタイムシステムは、仮想マシンを含むことができる。前記仮想マシンは、Java(登録商標)仮想マシン又は共通言語ランタイム仮想マシンであることができる。前記一組の処理における処理の数は、前記一組のランタイムシステムにおけるランタイムの数以下に設定されることができる。
他の態様において、本技術は、データ処理装置に、一組の処理の中の各処理におけるランタイムシステムを初期化させ、共有メモリ領域にユーザーセッションに対応するユーザーコンテキストを格納させ、前記ユーザーセッションに対応するリクエストを受信させ、前記一組の処理の中から一つの処理を選択させ、前記リクエストを処理するために、前記選択された処理における前記ランタイムシステムに前記ユーザーコンテキストを関連づけさせるように操作可能なコンピュータプログラムプロダクトを特徴とする。
有利な実施例は、1又は2以上の次の特徴を含むことができる。前記選択された処理における前記ランタイムシステムに前記ユーザーコンテキストを関連づけるステップは、前記ユーザーコンテキストを前記選択された処理にバインドするステップを含むことができる。前記各処理におけるランタイムシステムは、仮想マシンを含むことができる。前記仮想マシンは、Java(登録商標)仮想マシン又は共通言語ランタイム仮想マシンであることができる。
本明細書で述べられる本技術は、1又は2以上の次の利点を実現するために実施できる。本技術は、概して、或るランタイムシステムにおける複合データ構造体を分解(disassemble)し、そして、別のランタイムシステムの本来のフォーマットでそれを再構築(reassemble)するために使用できる。更に詳しくは、本技術は、ランタイムシステム(例えばVM)間でオブジェクトを共有するために使用できる。共有可能なクラス及び共有可能なオブジェクトインスタンスは、自動的に識別される。共有可能なものとして自動的に識別されないクラスは、それでもそれらが共有可能かどうかを判定するために、手動で分析されることができる。共有可能なオブジェクトは、共有クロージャと呼ばれる組にグループ化され、この共有クロージャは、複数のランタイムシステムと関連づけられることができる。複数のタイプのオブジェクトが共有されることができ(例えば、ユーザーコンテキストを構成するオブジェクトを含む)、そして複数のバージョンのオブジェクトが生成され共有されることができる。共有されたオブジェクトは、複数のメカニズムを通じてアクセスされることができ、この複数のメカニズムは、1又は2以上のランタイムシステムと関連するアドレス空間に共有メモリ領域から前記共有オブジェクトをコピーしマッピングするステップを含む。他のランタイムシステムにおいて共有オブジェクトを無効又は使用不能とする方法で前記共有オブジェクトにおけるデータをランタイムシステムがオーバーライトすることを防止するために、前記共有オブジェクトに対するアクセスを制限することができる。また、共有オブジェクトは、削除されガーベッジコレクトされたものとしてマークされることもできる。
オブジェクトは、異なる物理マシン上のランタイムシステム(例えばクラスターアーキテクチャ)間で共有されることができる。ソースランタイムシステムにおけるランタイムメタデータに対する参照は、ターゲットランタイムシステムにおけるランタイムメタデータに対する参照で置き換えられ識別されることができる。ランタイムメタデータは、ターゲットシステムにロードされることができ、そしてこのようなランタイムメタデータに対する参照は、しきりに又はゆっくりと(例えば要求に応じて)プラグイン(plug-in)されることができる。前記オブジェクトの共有は、資源の消費を低減させることができ(例えば、オブジェクトが複数のランタイムシステムによって共有されるので、使用するメモリが少なくてすみ)、同様に、時間の消費も少なくてすむ(例えば、共有されたオブジェクトが複数のランタイムシステムにおいて生成又は初期化される必要がないので、少ない時間ですむ)。
本明細書において述べられる本技術は、また、拡張可能な方法でユーザーセッション間の分離を提供するために使用されることができ、これにより、多くのユーザーセッションに対応するリクエストをサーバーがしっかりと処理することを可能にしている。ユーザーセッションは、各ユーザーセッションに対し一つのVMを割り当て、そしてリクエストを処理するために前記VMをOSワーク処理にバインドすることにより、分離されることができる。ワーク処理の数は、スループットを増加させるために調整されることができる(例えば、ワーク処理の数は、サーバーに割り付けられたプロセッサの数と一致するように設定されることができる)。前記VMは、資源及び時間の消費を低減するために、ユーザーコンテキストを含んでオブジェクトを共有することができる。
或いは、各ユーザーセッションに対して一つのVMを割り当てることよりも、VMは、また、ユーザーセッション間で共有されることもできる。従って、サーバーは、固定された数のVMで実施されることができる。サーバーは、また、可変ではあるが制限された数(例えば最大値)のVMで実施されることもできる。ユーザーセッション間でVMを共有することは、ユーザーセッションごとのオーバーヘッドを低減させることができ、特に、ユーザーコンテキストが小さい環境において上記オーバーヘッドを低減させることができる。VMを共有するにもかかわらず、それでも、ユーザーセッションは、たった一つのVMと一つのユーザーコンテキストを各ワーク処理に取り付け、そして、上記取り付けられたユーザーコンテキストのユーザーセッションに対応するリクエストを処理するために上記取り付けられたVMを使用することにより、分離された状態を維持することができる。それでも、スループットは最適化されることができる。なぜなら、ユーザーコンテキストとVMの双方が、バインドされ、そしてワーク処理が利用可能な限り処理で実行されることができるからである。
上述した分離される方法でVMを共有するために、ユーザーコンテキストは、上記VMから分離されることができる。上記ユーザーコンテキストは、複数のVMによって、例えば、サーバーにおける全てのVMによってアクセス可能な共有メモリ領域にユーザーコンテキストを格納することによって、共有されアクセスされることができる。リクエストは、VMをワーク処理にバインドし、関連するユーザーコンテキストを前記VMと関連づけ、そして前記関連づけられたユーザーコンテキストと共に前記ワーク処理における前記VMを実行することにより処理されることができる。たった一つのVMと一つのユーザーコンテキストを同時に処理と関連づけることにより、ユーザーセッションは相互に分離され、従ってVM又はワーク処理がクラッシュしても、前記関連づけられたユーザーセッションのみが影響を受ける。
複数のメカニズムが、ユーザーコンテキストをVMに関連づけるために使用されることができ、そして複数のタイプのアクセスが、前記ユーザーコンテキストにおけるデータに対して提供されることができる。スループットは、ユーザーコンテキストをVMと関連づけるための低コストのメカニズムの使用(例えば、ユーザーコンテキストとVMを処理にマッピングすること)を通じて最適化されることができ、同様に、ブロッキングVMをそれらのワーク処理から取り外し、他のリクエストを処理するためにそれらのワーク処理を使用することにより、最適化されることができる。ユーザーコンテキストは、クラスターアーキテクチャにおいて共有されることができ、ここで、VMは、複数の物理マシンに分散される。配信処理(dispatcher process)又は配信コンポーネントは、全体の作業負荷を分散させるように、または、マシン間でユーザーコンテキストを共有する必要性を最小化するように、VM間でリクエストを分散するために使用されることができる。ユーザーコンテキストは、たとえVMが永久的にワーク処理にバインドされても、VM間で共有されることができる(そして、VMは、それ故に、ユーザーセッション間で共有されることができる)。
各ユーザーセッションについて個別のVMを割り当てること、或いは、上述した分離法でVMを共有することは、資源消費の観点から責任(accountability)を生じる。それは、特定のVMまたはオペレーティングシステム処理のための資源の消費をモニターするには分かりやすい方法ではあるが、VM又は処理において動作しているプログラムのどの部分が特定の資源の消費(例えば、メモリ、処理時間、或いはガーベッジコレクションに費やされる時間)の原因となっているかを判定することは極めて困難である。しかしながら、もし、VMにおいて動作するユーザーコンテキストが一つしかなければ、資源はユーザーセッションベースで説明されることができ、それは、多くの場合は望ましい。
本発明の一実施は、上述の利点の全てを提供する。
これらの一般的および具体的な態様は、コンピュータプログラム、方法、システム、装置、または、コンピュータプログラム、方法、システムの任意の組み合わせを用いて実施されることができる。本発明の1又は2以上の実施形態の詳細は、添付の図面を参照しながら以下に説明される。本発明の他の特徴、目的、および利点は、以下の説明、図面、請求項から明らかになるであろう。
図1は、クライアント/サーバーシステムのブロック図である。
図2は、図1のクライアント/サーバーシステムにおけるサーバーのブロック図である。
図3は、図2におけるサーバーの他のブロック図である。
図4は、図2のサーバーにおけるリクエストの処理を説明するための処理フローチャートである。
図5は、サーバーにおける共有オブジェクトの使用を説明するためのブロック図である。
図6は、オブジェクトインスタンスが共有可能であるかどうかを判定するための処理を説明するためのフローチャートである。
図7は、クラスが共有可能であるかどうかを判定するための処理を説明するためのフローチャートである。
図8及び図9は、共有オブジェクトを生成し使用するための処理を説明するためのフローチャートである。
図10は、複数のマシンでオブジェクトを共有するための処理を説明するためのフローチャートである。
図11は、サーバーにおける共有オブジェクトを使用するための処理を説明するためのフローチャートである。
図12は、図1のクライアント/サーバーシステムにおける他のサーバーのブロック図である。
図13は、図12におけるサーバーの他のブロック図である。
図14は、図12のサーバーにおけるリクエストの処理を説明するためのブロック図である。
図15は、図12のサーバーにおけるリクエストの処理を説明するための処理フローチャートである。
図16は、図1のクライアント/サーバーシステムのうちの他のサーバーにおけるリクエストの処理を説明するための処理フローチャートである。
各図面における同様の参照番号及び記号は、同様の要素を示す。
ユーザーセッションの分離(Isolating User Session)
図1は、クライアント/サーバーシステム100を示し、同図において、ネットワーク150を介して、サーバー200はクライアントシステム102,104,106と接続される。サーバー200は、本発明による装置、プログラム、方法の実施に適したプログラム可能なデータ処理システムである。サーバー200は、ユーザーリクエストを処理する1又は2以上のランタイムシステムのためのコアオペレーティング環境を提供する。サーバー200は、プロセッサ202とメモリ250を備える。メモリ250は、オペレーティングシステムと、ネットワーク150を介して通信するためのTCP/IP(Transmission Control Protocol/Internet Protocol)スタックと、プロセッサ202によって実行されるマシン実行可能な命令(instruction)を格納するために使用されることができる。幾つかの実施例では、サーバー200は、複数のプロセッサを備えることができ、そのそれぞれは、マシン実行可能な命令を実行するために使用されることができる。メモリ250は、共有メモリ領域(shared memory area)255(後述の図に示される)を備え、この共有メモリ領域255は、サーバー200において実行する複数のオペレーティングシステムによってアクセス可能となっている。クライアント/サーバーシステム100で使用されることができる適切なサーバーの例としては、ドイツのSAP(登録商標)AG(SAP)によって開発されたウェブアプリケーションサーバー、或いは、NY,アーモンクのIBM(登録商標)社によって開発されたウェブスフェアアプリケーションサーバーのような、Java(登録商標)2プラットフォーム、エンタープライズ版(J2EE)コンパチブルのサーバーがある。
クライアントシステム102,104,106は、複数のアプリケーション又はアプリケーションインターフェイスを実行することができる。アプリケーションインターフェイス又はアプリケーションの各インスタンスは、ユーザーセッションを構成することができる。各ユーザーセッションは、サーバー200によって処理されるべき1又は2以上のリクエストを生成することができる。リクエストは、サーバー200上のランタイムシステム(例えばVM330)上で実行されるべき命令を含むことができる。
ランタイムシステムは、ユーザーリクエストにおけるコードまたは命令を実行するコード実行環境(code execution environment)であり、そのコードにランタイムサービスを提供する。コアランタイムサービス(core runtime services)は、処理(process)、スレッド(thread)、メモリマネージメント(例えば、サーバーメモリ250におけるオブジェクトの割り付け、オブジェクトの共有、オブジェクトに対する参照のマネージメント、オブジェクトのガーベッジコレクション)のような機能性(functionality)を含むことができる。機能強化されたランタイムサービスは、エラー処理や、セキュリティ及び接続性の確立のような機能性を備えることができる。
ランタイムシステムの一例として、仮想マシン(Virtual Machine ;VM)がある。仮想マシン(VM)は、実際のマシンまたはプロセッサのように、命令セット、一組のレジスタ(register)、スタック(stack)、ヒープ(heap)、メソッド領域(method area)を備えることができる概念上のマシンである。VMは、本質的には、プログラムコードが実行されるべき実際のプロセッサ又はハードウェアプラットフォームとプログラムコードとの間のインターフェイスとして振る舞う。プログラムコードは、VMの資源をコントロールするVM命令セットからの命令を含む。VMは、VMが動作するプロセッサ又はハードウェアプラットフォーム上で命令を実行し、そして、プログラムコードの命令を発効させるために、これらプロセッサ又はハードウェアプラットフォームの資源をコントロールする。このようにして、同一のプログラムコードが、各プロセッサ又はハードウェアプラットフォームのために再コンパイル又は再書き込みされる必要なく、複数のプロセッサ又はハードウェアプラットフォーム上で実行されることができる。その代わり、VMは各プロセッサ又はハードウェアプラットフォームのために実施され、そして同一のプログラムコードが各VMにおいて実行されることができる。VMは、プロセッサ又はハードウェアプラットフォームによって認識されるコードの形態で実施されることができる。或いは、VMは、プロセッサに直接的に組み込まれるコードの形態で実施されることができる。
一例として、Java(登録商標)ソースプログラムは、バイトコードとして知られるプログラムコードにコンパイルされることができる。バイトコードは、任意のプロセッサ又はプラットフォーム上で動作するJava(登録商標)VM上で実行されることができる。Java(登録商標)VMは、一回に一つの命令のバイトコードを解釈(interpret)することができる、または、バイトコードは、ジャストインタイム(just-in-time ;JIT)で実際のプロセッサ又はプラットフォームのために更にコンパイルされることができる。
Java(登録商標)VMに加え、VMの他の例は、アドバンスドビジネスアプリケーションプログラミング言語(Advanced Business Application Programming language ;ABAP)と、共通言語ランタイム(Common Language Runtime ;CLR)VMを含む。ABAPは、SAP R/3システムのための開発アプリケーション用のプログラミング言語であり、SAP(登録商標)により開発されたビジネスアプリケーションシステムに広くインストールされている。共通言語ランタイムは、WA,レッドモンドのマイクロソフト(登録商標)社により開発された管理コード実行環境(managed code execution environment)である。説明の簡略化のため、本明細書における議論は、仮想マシンに焦点を当てるが、本明細書で述べられる本技術は、他のタイプのランタイムシステムでも使用できることが理解されるべきである。
ユーザーセッションを互いに分離し、これによりシステムのロバスト性を増すために、サーバー200は、各ユーザーセッションにそれぞれVMが提供されるように実施されることができる。更に詳しくは、各ユーザーセッションには、それぞれ、PAVM(Process-Attachable Virtual Machine)が提供され、PAVMは、OS処理に取り付けられる(attach)と共にOS処理から取り外される(deattach)ことが可能なVMである。
図2は、処理取り付け可能なVM(process-attachable VMs)を使用するサーバー200の実施例を示す。処理取り付け可能なVMのインスタンスが作成され−例えば、VM301は、そのインスタンスが作成されてユーザーセッション1のために使用され、そして、VM303は、そのインスタンスが作成されてユーザーセッション2のために使用される。通常、もし、U個のユーザーセッションが存在すれば、サーバー200は、U個の対応するVMを備える。これは、図2においてユーザーセッションUに対応するVM309によって概念的に示されている。
また、図2に示されるサーバー200の実施例は、共有メモリ領域255を備え、この共有メモリ領域は、処理取り付け可能なVM、ワーク処理のプール(pool)400、配信処理410を格納するために使用される。ワーク処理のプール400は、サーバー200に割り付けられた多数のオペレーティングシステム処理−例えばワーク処理401,403,409を含む。概して、図2においてワーク処理409によって概念的に示されるように、P個のワーク処理をサーバー200に割り付けることができる。同期オーバーヘッドとコンテキストスイッチの個数を低減させるために、サーバー200に割り付けられたオペレーティングシステム処理Pの数は、概ね、サーバー200が動作するコンピュータ上で利用可能な処理の数と等しくなければならない。しかしながら、増強された分離(isolation)とロバスト性(robustness)の利益は、サーバー200がユーザーリクエストを処理するために、たった一つのオペレーティングシステム処理しか備えない場合でさえ達成されることができる。
オペレーションにおいて、図2のサーバー200がリクエストを受信すると、特殊な処理(配信処理410)が、ワーク処理プール400における利用可能なワーク処理の一つに対してリクエストを配信する。そのリクエストがユーザーセッション1に対応し(それがVM301に対応し)、且つ、配信処理410がそのリクエストをワーク処理401に配信すると仮定すると、サーバー200は、そのリクエストを処理するために、ワーク処理401にVM301を取り付け(attach)またはバインド(bind)する。そのリクエストが処理された後、サーバーは、ワーク処理401からVM301を取り外すことができる。そして、ワーク処理401は、他のリクエストを処理するために使用されることができる。例えば、もし、サーバー200がユーザーセッション2に対応する新たなリクエストを受信し、配信処理410が、そのリクエストをワーク処理401に配信すれば、対応するVM303は、この新たなリクエストを処理するためにワーク処理401に取り付けられることができる。この例の説明を続けると、もし、ユーザーセッション2に対応するリクエストを処理するためにワーク処理401が依然として使用されている間にサーバー200がユーザーセッション1に対応する他のリクエストを受信すれば、配信処理410は、ユーザーセッション1からワーク処理403に新たなリクエストを配信し、そしてユーザーセッション1のためのVM301が、ユーザーセッション1からの新たなリクエストを処理するためにワーク処理403に取り付けられることができる。
サーバー200は、配信処理410を備える必要はない。例えば、代替の実施例では、ユーザーリクエストは、サーバー200に割り付けられた処理に連続的に割り当てられることができる。各処理は、リクエストのキュー(queue)を保持し、そしてそのリクエストに対応するユーザーセッションの処理取り付け可能なVMを、そのリクエストを処理するために、そのキューの前(front)に取り付けることができる。
上述したように、処理取り付け可能なVMは、OS処理に取り付け可能であるとともにOS処理から取り外し可能なVMである。処理からVMを取り外すために(そして、そのVMを他の処理に取り付けるために)、VMと該VMが動作する処理との間の親和性(affinity)は除去される必要がある。VMが処理から取り外される場合、VMのステートは存続される必要がある。VMが他の処理に取り付けられる場合、このVMのステート(state)は存続されてはならない。従って、VMのステートは、そのステートを存続させることを可能とすると共にそのステートを存続させないことを可能とするような方法で保持され発生される必要がある。さらに、処理からVMを取り外すときにVMのステートを存続すること、及びVMを別の処理に取り付けるときにVMのステートを存続させないことは、望ましくは、低コストのオペレーションであるべきである。このことは、サーバーに割り当てられたOS処理にアクセス可能である共有メモリ領域にVMのステートを格納することにより達成される。
また、共有メモリに配置されたVMがユーザーセッションに対応するユーザーコンテキストをアクセスするために、ユーザーコンテキスト−ユーザーヒープ(user heap)とユーザースタックの両方を含む−は、共有メモリに配置されなければならない。(或いは、ユーザーコンテキストは、VMがバインドされた処理のアドレス空間にコピーされることができ−このような実施例は以下で更に詳しく説明される。)従って、サーバー200の一実施例において、ユーザーコンテキストは、また、共有メモリに格納される。共有メモリにユーザーヒープを格納することは正攻法である−上記ヒープ用のメモリは、共有メモリセグメントから単に割り当てられることができる。上記ユーザースタックを格納することはより困難である。なぜなら、Java(登録商標)VMと同様に、いくつかのインスタンスでは、ユーザースタック及びVMスタックは混合(intermix)されるからである。この場合、一つの解法は、ユーザースタックを含んで、VMのスタックの全てを共有メモリに格納することである。一実施例において、このことは、VMをオペレーティングシステムコルーチン(operating system co-routine)として実施することにより達成される。
典型的なサブルーチンは階層的関係を呈する。例えば、サブルーチンAは、サブルーチンBを呼び出すときにサスペンド(suspend)し、そしてサブルーチンBが終了すると制御をサブルーチンAに戻し、そしてサブルーチンAはサスペンドした点から実行を再開する。一方、コルーチンは、階層的関係というよりも、むしろ並列的関係を有する。従って、例えば、コルーチンAは、コルーチンBを呼び出すとサスペンドするが、コルーチンBは、また、制御をコルーチンAに戻したときにサスペンドする。コルーチンBに対しては、この制御の返還はコルーチンAの起動のようなものである。その後、コルーチンAがコルーチンBを読み出してサスペンドすると、コルーチンBは、コルーチンAの前回の起動がリターンされるように振る舞い、そして、それは、その起動の点から実行を再開させる。従って、制御が二つのコルーチンの間で往来し、それぞれが、前回の中止位置で再開する。
いくつかの実施例において、コルーチンのそれぞれが固有のスタックを備え、ヒープを共有(share)するので、コルーチンはスレッドと比較されることができる。しかしながら、スレッドとコルーチンとの一つの違いは、オペレーティングシステムがスレッド間のスケジューリングを処理するのに対し、プログラマーがコルーチン間のスケジューリングを管理しなければならないことである。コルーチンは、後述するように、スレッドを模擬するために使用される。例えば、Linux glibc ライブラリー内の一組の機能は、setcontext( ),getcontext( ),makeconetxt( ),swapcontext( )の各機能を備え、コルーチン間で切り替えるために、そして重要なことには、コルーチンのスタック用のメモリを提供するために、処理内の新たなコルーチンをスタートさせるために使用されることができる。この最後の特徴は、共有メモリからVMのスタックを割り当てるために(そして、共有メモリにスタックを格納するために)使用されることができる。
サーバー200の一実施例において、ユーザーセッションが開始するとき、このユーザーセッションに対応する処理取り付け可能なVMが生成され初期化される。“セッションメモリ”と呼ばれる、共有メモリのプライベートブロックはVMに割り当てられる。VMのヒープとスタックは、共有メモリのこのプライベートブロックから直接的に割り当てられる。オペレーティングシステム処理は、単にVMのセッションメモリをそのアドレス空間にマッピング(map)することができるだけであるから、VMのステートを格納するために共有メモリを使用することは、VMをOS処理に取り付け又はバインドする処理を実質的にノンオペレーション(non-operation)にする。同様に、OS処理からVMを取り外す処理は、単に、OS処理のアドレス空間からVMのセッションメモリをマッピング解除(unmapping)することを必要とする。データは、実際には移動またはコピーされない。
また、処理からVMを取り外すこと(そして、VMを他の処理に取り付けること)を可能とするためには、ファイルハンドル(file handle)やソケット(socket)のような、VMによって使用される入力/出力(I/O)資源も存続される必要がある。VMによって使用されるI/O資源は、資源を存続させること及び存続させないことを可能にするような方法で生成され維持される必要がある。このことは、I/O資源をアクセスするためのインディレクション(indirection)の追加的レベルを使用することにより達成されることができる。例えば、VMがファイル又はソケットディスクリプターとして見ることは、実際には丁度、ファイル又はソケットへのハンドル(handle)である。ハンドルは、それ自体、存続可能(persistable)であり、例えば、ファイルハンドルは、VMのセッションメモリに格納されることができる。或いは、ハンドルは、資源マネージャの使用を通じて存続可能とされることができ−例えば、ソケットの場合、デスクリプターパッシング(descriptor passing)が、特定のソケット用のI/OリクエストのためのI/Oリクエストに関するソケットマネージャを通知するために使用されることができる;そしてソケットマネージャは、I/Oリクエストが完了されると配信手段を通知することができる。
いくつかのVMは、マルチスレッドであってもよい。スレッドは、本質的には、単一プログラムの使用の範囲内で複数のサービスリクエスト又はコンカレントユーザーをプログラムが処理することを可能にするプレースホルダー情報(placeholder information)である。プログラムの観点から、スレッドは、一人の個人ユーザー又は特定のサービスリクエストを扱うのに必要な情報である。もし、複数のユーザーがプログラムを一斉に使用し、又はプログラムが同時に多数のリクエストを受信すれば、スレッドは、このような各ユーザー又はリクエストのために生成されて維持される。このスレッドは、プログラムが、異なるユーザー又はリクエストの代わりに交互に再入力reenter)されるので、どのユーザー又はリクエストが扱われているのかをプログラムが知ることを可能にする。
本来のOSスレッド(native OS thread)は、容易に共有メモリに存続(persist)されることができる。従って、マルチスレッドのVMを処理から取り外すことを可能にするためには(そして、VMを他の処理に取り付けることを可能にするためには)、本来のスレッドは、ユーザーレベルのメカニズムにより模擬(simulate)されることができる。本来のスレッドを模擬するためにユーザーレベルのメカニズムを導入することは、“グリーンスレッド(green thread)”機能性を提供すると呼ばれる。グリーンスレッドは、オペレーティングシステムよりもユーザーによってスケジュールされるユーザーレベルのスレッドである。
本来のスレッドを模擬するために使用することができる一つのメカニズムは、オペレーティングシステムコルーチン(operating system so-routines)である。上述したように、コルーチンは、(オペレーティングシステムよりは)プログラマーがコルーチン間のスケジューリングを管理することを除いては、スレッドに似ている。従って、VMスレッドを実施するために使用できる本来のOSスレッドは、コルーチンにマッピングされることができる。スレッドのコールスタック(call stacks)、ミューテックス(mutexes)、Java(登録商標)モニターのための条件変数(condition variables)を含んで、スレッドマネージメント及びスケジューリングに関連する全てのデータ構造は、VMのセッションメモリに保持されることができる。Java(登録商標)VMの場合では、それは、例えば動的メソッド起動(dynamic method invocation)のJNI(Java(登録商標) Native Interface)実施のために、VM実施によって使用されるCスタック及びJava(登録商標)スタックの両方を含むことができる。
通常、オペレーティングシステムは、フェアネス(fairness)を最大化するために(すなわち、或る時点で稼動する機会を各スレッドに与えるために)、先制してスレッドをスケジューリングする。一方、プログラマーによって扱われるコルーチンスケジューリングは、通常、先制的ではない。しかしながら、それは、必ずしも欠点ではなく、サーバーとの関連で、リクエストスループットは、しばしばフェアネスよりも重要である。リクエストスループットは、拡張性にとって主要目的であり、コルーチンをスケジューリングするためのバッチ処理法を用いることにより最大化されることができる。バッチ処理法において、各VM内では、各コルーチンは、ウェイトステートに入るとき(例えば、Java(登録商標)モニターのようなモニター又はI/O上でのブロッキングのとき)、スケジューラー(時々、スレッドスケジューラと呼ばれる)に協力的に服従する。ブロッキングI/Oコールとスレッドスケジューラとの間の調整(coordination)は、上述したI/O出力先変更メカニズム(I/O redirection mechanism)の一部として含まれることができる。ミューテックス及び条件変数は、セッションメモリにおけるスケジューラー制御の変数として基本命令(primitives)を固定(lock)するオペレーティングシステムを用いることなく実施されることができる。
コルーチンスケジューリングは、その全てのコルーチンがウェイトステートに入るまで、PAVMのために継続することができ、つまり、ユーザーリクエストが完了したか、またはI/Oを待っている。何れの場合においても、PAVMは、ワーク処理から取り外されることができる。配信処理410は、次のリクエストがユーザーセッションから到来したとき、またはI/Oリクエストが完了したときに、利用可能なワーク処理にPAVMを再取り付けすることができる。
上述したように、VMスレッドを実施するために使用される本来のスレッドは、コルーチンにマッピングされることができる。一方、例えばガーベッジコレクションなどのために、VMにおいて内部的にのみ使用される本来のスレッドは、同期ファンクションコール(synchronous function calls)で置き換えられることができる。同期ファンクションコールを使用することは、内部的な本来のスレッドを模擬する手段として考えられる。或いは、もし、内部的な本来のスレッドによって実行されるべきファンクションが非同期的に実行されるのであれば、このファンクションは、サーバー内の指定された優先度の低い処理上で実行されスケジューリングされることができる。さらに他の代替は、いくつかのファンクションを一緒に削除(omit)することである。例えば、ユーザーセッションがアクティブである期間中にガーベッジコレクションを遂行するよりも、むしろ、ユーザーセッションが終了したときに全てのセッションメモリを単に開放することの方が可能である。
図3は、Java(登録商標)2プラットフォーム,エンタープライズ版(J2EE)アプリケーションサーバー200の例を示し、アプリケーションサーバー200は、共有メモリ255とワーク処理401,403を備える。J2EEは、大企業に特有なメインクレーム規模のコンピューティングのために設計されたJava(登録商標)プラットフォームである。J2EEは、標準化された再利用可能なモジュラーコンポーネントを生成し、そして層(tier)がプログラミングの多くの局面を自動的に処理することを可能とすることにより、階層的(tiered)で薄いクライアント環境においてアプリケーション開発を簡略化する。J2EEは、Java(登録商標)2ディベロップメントキット(JDK)のような、Java(登録商標)2プラットフォーム,標準版(J2SE)の多くのコンポーネントと、CORBA(Common Object Request Broker Architecture)、JDBC(Java(登録商標) Database Connectivity 2.0)、セキュリティモデルのためのサポートを含む。また、J2EEは、EJB(Enterprise Java(登録商標) Beans)、API(Java(登録商標) servlet application programming interface)、JSP(Java(登録商標) Server Pages)のためのサポートを含む。
各ワーク処理401,403は、コンテナー204と、RMI(Remote Method Invocation)インターフェイス206及びデータベースマネージメントシステム(DB)インターフェイス208のようなサービスインターフェイスを備えることができる。RMIは、異なるコンピュータ上のオブジェクトが分散型ネットワーク上で相互通信することを可能にするオブジェクト指向のプログラミング技術である。RMIは、一般にRPC(Remote Procedure Call)として知られているJava(登録商標)版のプロトコルであるが、リクエストと一緒に1又は2以上のオブジェクトを通過する追加的能力を備えている。
コンテナー(container)204は、本来のOSによって提供されるフレームワークよりもサーバーアーキテクチャに適したフレームワークを提供するOSインターフェイスを備えることができる。このOSインターフェイスは、スケジューリング、メモリ管理、処理アーキテクチャ、クラスタリング、ロードバランシング、ネットワーキングなどのように、本来のOSから一定のファンクションに対する責務を引き継ぐことができる。このようなファンクションを引き継ぐことにより、コンテナー204は、リクエストスループットのような一定の対象を最適化するように、プロセッサやメモリのような重要な資源の使用を制御することができる。また、コンテナー204は、サーバー上で動作するアプリケーションからサーバーの本来のオペレーティングシステムの詳細を隠す役目を果たすことができる。
加えて、コンテナー204は、インターフェイスとしての役目も果たすことができ、このインターフェイスを通じて、処理取り付け可能なVMが処理に取り付けられ、その処理において実行され、そして、その処理から取り外される。従って、図3に示されるサーバーの実施例において、コンテナー204は、(例えば、VMに割り当てられた共有メモリブロックを処理のアドレス空間にマッピングすることにより)VMのステートを存続させることや存続させないこと、およびVMのスレッド又はコルーチンのスケジューリングのような、処理取り付け可能なVMの使用のための幾つかの機能性を提供する。
図3の例において、第1のユーザーセッション(ユーザーセッション1)は、ワーク処理401にバインドされている。ユーザーセッション1は、対応するユーザーコンテキスト501及びVM301を備える。共有メモリ255のブロック257は、ユーザーセッション1に割り付けられている。ユーザーコンテキスト501およびVM301のステートは、共有メモリブロック257に格納される。この例では、ユーザーセッション1に対応するリクエストは、ワーク処理401に配信され受信されている。このリクエストを処理するために、ユーザーセッション1に対応するVM301は、ワーク処理401にバインドされる。従って、ユーザーコンテキスト501とVM301のステートの両方は、共有メモリブロック257からワーク処理401のアドレス空間にマッピングされている。そして、VM301は、リクエストを処理するためにワーク処理401によって実行される。リクエストが処理されると、ユーザーセッション1は、ワーク処理401からバインド解除(unbind)されることができ、つまり、対応するVMとユーザーコンテキストは、(例えば、ワーク処理401のアドレス空間からVM301のステートとユーザーコンテキスト501をマッピング解除(unmapping)することにより)ワーク処理401から取り外されることができる。
また、図3は、ワーク処理403にバインドされたユーザーセッション2を示す。ユーザーセッション2は、対応するユーザーコンテキスト503とVM303を備える。共有メモリ255のブロック259は、ユーザーセッション2に割り当てられる。ユーザーコンテキスト503及びVM303のステートは、共有メモリブロック259に格納され、そしてワーク処理403のアドレス空間にマッピングされる。ユーザーセッション2からのリクエストが処理されると、ユーザーセッション2は、ワーク処理403からバインド解除(unbind)されることができ、つまり、(例えば、ワーク処理403のアドレス空間からユーザーコンテキスト503とVM303のステートをマッピング解除することにより)ワーク処理403から、対応するVMとユーザーコンテキストが取り外されることができる。
VM303がウェイトステート(wait state)にあるか、または、VM303がユーザーセッション2からのリクエストの処理を完了したために、VM303がワーク処理403から取り外されたと仮定すると、もし、新たなリクエストがユーザーセッション1から到着すれば、この新たなリクエストは、例えばワーク処理403に配信されることができる。そして、ユーザーセッション1に対応するユーザーコンテキスト501及びVM301は、ワーク処理403にバインドされることができる。一実施例において、このことは、如何なるデータの移動やコピーを必要とせず−むしろ、共有メモリブロック257(又はその適切な一部)は、ワーク処理403のアドレス空間に単にマッピングされるだけである。そして、ワーク処理403は、ユーザーセッション1からの新たなリクエストを処理するためにVM301を実行することができる。
従って、ユーザーセッションは、異なる処理にバインドされることができ、異なる処理間で移動することができる。このように、リクエストは、ワーク処理が利用可能になるとすぐに処理されることができる。さらに、ユーザーセッションを異なる処理にマッピングすることは、通常、非常に安価なオペレーションである。その結果、リクエストスループットが最適化される。また、リクエストスループットが、サーバーにさらに多くの処理を割り付けることにより最適化されることができるので、処理取り付け可能なVMは、サーバーに拡張性をもたらす。また、さらに多くの処理をより良く扱うために、潜在的コンピュータ(underlying computer)に更に多くの処理を加えることが可能である。
また、処理取り付け可能なVMの使用はサーバーを堅牢にする。このことは、OSが、処理(例えば、サーバー処理プール400におけるワーク処理)間で提供する分離(isolation)によるものである。また、一つのユーザーセッションのメモリとVMのみを1度にワーク処理にマッピングすることにより、ユーザーセッションに関連するステータスとメモリを保護することが可能である。
サーバー200の別の実施例において、2又はそれ以上のPAVMが、一つの処理に取り付けられて、この一つの処理内で実行される。例えば、ABAP VM及びJava(登録商標)VMが一つの処理内で実行されることができる。一つの処理内でABAP VMとJava(登録商標)VMを動作させることは、同一のアプリケーションにおいてABAP VMとJava(登録商標)VMの両方の使用を可能にする。従って、アプリケーションは、ABAP VMとJava(登録商標)環境の両方からの有用なコンポーネントを活用するように開発されることができる。後述する技術は、一つの処理内で複数のVMを実行するために使用されることができる。例えば、処理は、Java(登録商標)VM、およびABAP VM、およびCLR VMを実行するために使用されることができる。
一つの処理内での複数のVMの実行は、コルーチンの使用を通じて達成することができる。ABAP VMとJava(登録商標)VMが一つの処理内で動作する例では、二つのコルーチンが使用されることができる−一つはABAP VMのために使用され、もう一つはJava(登録商標)VMのために使用される。Java(登録商標)VM又はABAP VMの何れかを備えることに加え、各コルーチンは、また、スケジューリングのようなファンクションと、サーバー外部のアプリケーションだけではなく二つのVM間の通信とを処理するために、コンテナー(またはコンテナーの一部)を備えることができる。
ABAP/Java(登録商標)の例を続けると、もし、ABAP VMが、アプリケーションが使用するであろう主要なVMであれば、ABAP VMを実行するコルーチンは、上述したようなコンテナーを備えることができる。ABAP VM内で実行するリクエストが最初にJava(登録商標)オブジェクトをコールしたとき、そのコンテナーは、Java(登録商標)VMスタック(Java(登録商標)ユーザースタックを含む)のためにメモリを割り当て、そして、Java(登録商標)VMを実行するために新たなコルーチンを開始させる。この新たなコルーチンに受け渡されるパラメータは、新たなコルーチンのためのスタートファンクションだけでなく(この場合、Java(登録商標)VMそのもの)、割り当てられるメモリのサイズと場所を含む。そして、Java(登録商標)VMは、メインクラス、例えば、Java(登録商標)サーブレット、エンタープライズJava(登録商標)ビーンズ、またはJava(登録商標)サーバーページのような、J2EEコンポーネントを動作させるために使用できるJ2EEコンテナーの実施を開始させることができる。それが実行している間、Java(登録商標)VMは、例えば、メッセージエリアからリクエストを読み出し、そしてレスポンスをメッセージエリアに書き込むためのコンテナー機能性を起動させることができる。スケジューリングのために、Java(登録商標)VMは、リクエストをメッセージエリアから読み出し、レスポンスをメッセージエリアに書き込んだ後、制御をABAP VMに戻すことができる。そして、Java(登録商標)VMは、新たなリクエストまたはそれ自体のリクエストの何れかが到着すると、すぐに、再スケジューリングされることができる。
図4は、図2に示されるサーバー実施例においてリクエストを処理するための処理450の例を説明するためのフローチャートである。処理450は、処理取り付け可能なVMの使用を通じて拡張可能な方法でユーザーセッション間の分離を提供する。ユーザーセッションが開始すると、そのユーザーセッションのために、処理取り付け可能なVMが生成されて初期化される(452)。このオペレーションは、VM用のメモリのブロックの割り当てを含む。割り当てられたメモリは、(VMがサーバーにおける複数の処理によってアクセスされることを可能にするための)共有メモリであることができ、また、プライベートとして指定されることができ、つまり、メモリのブロックが新たに生成されたVMに単独で属する。
メモリのブロックがVMに割り当てられた後、VMは、メモリブロックに格納されることができる。(VMスタック及びヒープを含む)VMの計算ステート(computational state)と、(ユーザースタックとヒープを含む)対応ユーザーセッションのためのユーザーコンテキストは、全てメモリブロックに格納されることができる。ユーザーコンテキストは、ファイルのようなI/O資源に対するハンドルと、ソケット(socket)のようなI/O資源のためのプロキシに対するハンドル(例えば、資源マネージャ)を含む。
VMを初期化することは、システムクラスにおける多数のスタティックイニシャライザーの実行だけでなく、ロード(loading)、検証(verifying)、多くのクラス(例えば、Java(登録商標)システムクラス)の分解(resolving)を起動するので、高価なオペレーションである。このような初期化オーバーヘッドは、予め初期化された“マスター”VMの使用を通じて低減されることができる。スクラッチ(scratch)からの新たなVMを初期化するよりも、むしろ、マスターVMのメモリブロックは、新たなVMのメモリブロックに単にコピーされることができる。マスターVMのメモリブロックのテンプレートイメージを新たなVMのメモリブロックにコピーすることは、既に初期化されたステートで新たなVMが動作を開始することを可能にする。もし、或る初期化オペレーションが、新たなVMが実際に起動したときに実行されるのみであれば、部分的に初期化されたVMのテンプレートイメージは使用されることができ、従って、起動した後、すぐに、新たなVMは、起動の最中に実行される必要のあるそれらのオペレーションを実行すればよいだけである。
(実行と同様に)初期化オーバーヘッドは、他の最適化:全てのVMによってアクセスされることができる共有メモリのセクションにタイプ情報(例えば、ロードされたクラスのランタイム表現)を格納することを通じてさらに低減することができる。この技術は、クラスローディング、検証、各VMによって負担された分解能(resolution)のためのオーバーヘッドを低減することができ、そして、あらゆるユーザーコンテキストによって使用されそうなシステムクラスのバイトコードを共有するために使用されれば、特に有用である。類似の技術は、ユーザークラスのバイトコードを共有するために使用されることができる。また、コンパイルされたコードは、ジャストインタイム(JIT)コンパイラーが使用される実施例で共有されることができる。
VMが初期化された後、VMは、対応するユーザーセッションからのユーザーリクエストを処理するために使用されることができる。対応するユーザーセッションからのユーザーリクエストが受信されると(454)、サーバーに割り付けられた処理のプールからの利用可能な処理が、リクエストを処理するために選択される(456)。そして、リクエストを送ったユーザーセッションのPAVMは、選択された処理にバインドされる(458)。
もし、VMを格納するために使用されるメモリブロックが、サーバーの全ての処理によってアクセスされることができる共有メモリであれば、バインドは、実質的にノンオペレーションであることができる−例えば、メモリブロックまたはその一部が、選択された処理のアドレス空間に単にマッピングされることができる。マッピングされた部分は、VMの計算ステート(computational state)を含むことができる。或いは、VMは、別の方法で存続されないようにできる。例えば、VMの計算ステートはファイルからコピーされることができる。しかしながら、このようなオペレーションの性能は悪く、特に、共有メモリを処理アドレス空間にマッピングする効率的オペレーションと比較して悪く、それは、通常、データのコピーや移動を必要としない。
選択された処理にVMがバインドされた後、VMは、ユーザーリクエストを処理するために処理によって実行されることができる(460)。このことは、VM内のスレッドを模擬するための2又はそれ以上のコルーチンの実行を起動することができる。また、それは、内部スレッド(例えば、ガーベッジコレクションを実行するためのスレッド)の実行を模擬するための同期ファンクションコールの実行を起動することができる。もし、このような内部スレッドまたは他のファンクションが非同期に実行されれば、サーバーに割り当てられた処理のうちの一つが、優先度の低い処理として指定され、そして、VMのためのファンクションを実行するために使用される。この技術は、例えば、VMにおけるガーベッジコレクションを実行するために使用されることができる。さらに重要なファンクションは、優先度が通常の処理または優先度が高い処理の何れかにおいて動作するようにスケジューリングされることができる。
VMがユーザーリクエストを処理した後、VMは、選択された処理から取り外される(462)。そして、この選択された処理は、サーバーによって受信される新たなリクエストを処理するために使用されることができるように、利用可能な処理のプールに戻されることができる(或いは、使用可能であるようにマークされる)。バインドと同様に、処理からVMを取り外すことは、単純で低コストのオペレーションである:共有メモリのVMのブロックは、単に処理アドレス空間からマッピング解除される。或いは、VMを存続させることは、ファイルにVMの計算ステートをセーブするなどのように、より複雑で高価なオペレーションを起動してもよい。VMを処理にバインドすること又は取り付けることと、その処理からVMをバインド解除すること又は取り外すことは、お互いに鏡像の関係にある−すなわち、VMを存続させないために実行されるオペレーションは、VMを存続させることと逆のオペレーションである。そして、サーバーは、ユーザーセッションからの他のリクエストを待つことができる(454)。
ユーザーセッションが終了すると、その対応するVMもまた終了され、そして、その割り当てられたメモリを含むその資源の全てが開放されることができる。もし、VMのメモリが、ユーザーセッションの終わりで開放されれば、VMが存在する間にガーベッジコレクションを省略(omit)することが可能である。ユーザーセッションの終わりでVMを終了させることの代替手段は、VMを再使用することであり、すなわち、VMを他のユーザーセッションと関連づけ、そして、そのユーザーセッションに対応するリクエストを処理するためにそのVMを使用することである。この技術は、保持されるのに非常に小さなユーザーコンテキスト(またはユーザーコンテキストなし)を必要とするアプリケーションにとっては特に有用であり、非常に短いユーザーセッションを有するアプリケーションについても同様である。(保持されるのにユーザーコンテキストを必要としないアプリケーションは、時折、ステートレスアプリケーションと呼ばれる。)このような全てのアプリケーションについて、連続的に再使用可能なVMのプールを使用することは、VMを生成し、初期化し、保持し、終了することに関連したオーバーヘッドを最小化するのに役立つことができる。
処理取り付け可能なVMの使用と実施例に関する追加的な詳細は、N.Kuck, H.Kuck, E.Lott, C.Rohland, and O.Schmidt, SAP VM Container: Using Process Attachable Virtual Machines to Provide Isolation and Scalability for Large Servers(August 1, 2002)(非公開の要約が提出され、そして2nd USENIX Java(登録商標)仮想マシン研究技術シンポジウム(Java(登録商標)VM‘02)に途中報告として示されている)において述べられている。
共有オブジェクトの生成および使用(Creating and Using Shared Object)
各ユーザーセッションに一つのVMを割り当てることは、各ユーザーセッションは、それ自身のVMヒープ(例えばJava(登録商標)ヒープ)を備えることを意味する。従って、シングル、マルチスレッドVMを使用するサーバー200の実施例において一度だけ存在するだけのVMヒープにおけるデータオブジェクトは、各ユーザーセッションのために一度だけ複製(replicate)される。このことは、資源の消費(例えば、複製されたデータオブジェクトを格納するためのメモリ)と時間の消費(例えば、複製されたデータオブジェクトを構築して初期化するための時間)の両方をもたらす。
簡単な例として、アプリケーションの起動時に解析される拡張マークアップ言語(XML)構成ファイル(configuration file)を表す大規模なJava(登録商標)データ構造を考える。上記アプリケーションに対応する各ユーザーのためのこのようなデータ構造の複製処理において、サーバー200は、CPU時間(XMLファイルを解析し、データ構造を構築するための時間)とメモリ(データ構造を格納するためのメモリ)の両方を第1のVMとユーザーセッションとを除く全てのために消費する。
この問題を解決するため、サーバー200の一実施例は、データオブジェクトがVM間で共有されることを可能にする。サーバー200のこの実施例において、共有メモリ領域またはヒープが、複数のVMによってアクセス可能なデータオブジェクトを格納するために使用される。
共有メモリヒープにおけるデータオブジェクトは、通常、如何なるプライベートヒープ(例えば、個々のVMのプライベートヒープ)に対しても参照(references)又はポインタ(pointers)を有しない。これは、もし、共有メモリヒープにおけるオブジェクトが一つの特定のVMにおけるプライベートオブジェクトに対する参照と共にメンバー変数を有しているとすれば、その参照は、その共有オブジェクトを使用する他の全てのVMにとって無効(invalid)であるからである。さらに正式には、この制限は次のように考えられる:何れの共有オブジェクトについても、初期オブジェクトによって参照されるオブジェクトの推移的クロージャ(transitive closure)は、常に共有オブジェクトを含むだけである。
従って、サーバー200の一実施例において、オブジェクトは、それ自身によって共有メモリに格納される−正確に言えば、オブジェクトは、“共有クロージャ”として知られるグループにおける共有メモリヒープに格納される。
共有クロージャを通じたオブジェクトの共有は、図5に概念的に示され、同図において、共有クロージャ600は、第1のオブジェクト601によって参照される全てのオブジェクトの推移的クロージャと共に第1のオブジェクト601をグループ化することにより第1のVM301において識別(identify)される。共有クロージャ600が識別された後、VM301は、例えば、共有クロージャ600を共有メモリ領域255にコピーすることにより、共有メモリ領域255に共有クロージャを生成することができる。共有クロージャ601が共有メモリ領域255に生成された後、それは、サーバー(例えば、VM301,303,305)におけるVMによってアクセスされることができる。VMは、例えば、共有メモリ領域255からVMが稼動している処理のアドレス空間に共有クロージャ600をマッピングまたはコピーすることにより、共有メモリ領域255から共有クロージャ600をアクセスすることができる。共有クロージャの生成及び使用は、以下において更に詳細に説明される。
共有クロージャ内で使用可能であるためには、オブジェクトは、“共有可能”でなければならない。通常、一つのランタイムシステム(例えばJava(登録商標)VM)における複合データ構造体(例えば、ヒープ、またはその一部)は、もし、データ構造の内部の一貫性または機能性を阻害することなく、データ構造を分解(disassemble)し、そして第2のランタイムシステムの本来のフォーマットで再構成(reassemble)することができれば、第2のランタイムシステムで共有されることができる。
サーバー200の一実施例において、オブジェクトは、共有クロージャを共有メモリにコピーし又は該共有メモリからコピーすることを通じて共有される。この実施例においてオブジェクトが共有可能であるためには、オブジェクトは、オブジェクトの機能性または内部的一貫性を阻害することなく、他のVMのアドレス空間に対する透過的ディープコピー(transparent deep-copy)に耐えることができなければならない。このような実施例のための共有可能性要件(shareability requirement)、は、以下で更に詳しく説明される。
通常、共有可能性のほとんどの態様はオブジェクトのクラスのプロパティであるにもかかわらず、オブジェクトインスタンスの共有可能性(shareability)は、このクラスのプロパティに依存しなのみならず、そのオブジェクトインスタンスのメンバー変数のタイプにも依存しない。メンバー変数が、実行時まで決定できないランタイムタイプを有することができる場合、共有クロージャ内のオブジェクトインスタンスの共有可能性は実行時に決定されなければならない。
従って、オブジェクトインスタンスがランタイムタイプを有するサーバー実施例において、共有可能なクラスと共有可能なオブジェクトインスタンスとの間に区別が設けられる。クラスは、以下に例が述べられるような共有可能性の基準(criteria)を満足すれば、共有可能なクラスである。オブジェクトインスタンスは、そのランタイムタイプが共有可能である場合、および、参照する全てのオブジェクトが共有可能なオブジェクトインスタンスである場合に、共有可能なオブジェクトインスタンスである。換言すると、オブジェクトインスタンスは、次の両方の条件が満たされれば、共有可能なオブジェクトインスタンスである:(i)オブジェクトのランタイムクラスが共有可能なクラスであること、および(ii)オブジェクトインスタンスのゼロでない参照タイプメンバー変数が共有可能なオブジェクトインスタンスであること。
第1条件(オブジェクトのランタイムクラスが共有可能なクラスであること)は、ランタイムクラスのインスタンスが共有に対処することが意味的(semantically)に可能であることを確保することを意味している。クラスが共有可能であるかどうかを判定するための基準の例が以下に提示される。ランタイムクラスが共有可能であるかどうかの判定は、各クラスについて一度だけなされればよいが、このような特性は、引き継ぐことができない。なぜなら、導出クラス(derived class)は、共有と互換性のない機能性を付け加えるからである。
第2条件(オブジェクトインスタンスのゼロでない参照タイプメンバー変数が、それ自体、共有可能なオブジェクトインスタンスであること)は、共有クロージャにおける全てのオブジェクトが共有可能であることを確保することを意味している。この条件が満足されるか否かは、オブジェクトインスタンスにおける参照の再帰的検査によって判定されることができる。“共有可能なクラス”特性の非引継性(non-inheritability)のために、オブジェクトの全てのメンバー変数の宣言されたタイプを単に検査することは、宣言されたタイプが共有可能であり、ランタイムタイプが共有可能でないとしても、十分ではない。
図4は、オブジェクトインスタンスが共有可能なオブジェクトインスタンスであるかどうかを判定するために使用できる処理650の例のフローチャートを示す。図6に示される処理において、最初に、オブジェクトインスタンスの識別が受信される(652)。オブジェクトインスタンスのランタイムクラスが識別され、そしてこのランタイムクラスが共有可能なクラスであるかどうかの判定が行われる(654)。もし、ランタイムクラスが共有可能なクラスでなければ(判定656のブランチ“no”)、処理は、オブジェクトインスタンスが共有可能でない旨の指示(indication)で終わる(658)。このような否定的な指示は、例えば、“共有不能(not shareable)”の例外を起こすことによりなされることができる。
もし、オブジェクトインスタンスのランタイムクラスが共有可能なクラスであれば(判定656のブランチ“yes”)、オブジェクトインスタンスによって参照されるオブジェクトが識別される(660)。そして、処理650は、参照されるオブジェクトをトラバース(traverse)して、その参照されるオブジェクトが共有可能なオブジェクトインスタンスであるかどうかを判定する。もし、参照されるオブジェクトがさらに存在すれば(判定662のブランチ“yes”)、残りの参照されるオブジェクトの一つが選択される(664)。そして、参照されるオブジェクトが共有可能なオブジェクトインスタンスであるかどうかの判定がなされる(666)。もし、参照されるオブジェクトが共有可能なオブジェクトインスタンスでなければ(判定668のブランチ“no”)、処理650は、初期オブジェクトインスタンスが共有可能でない旨の指示(indication)で終わる(658)。これは、初期オブジェクトインスタンスによって参照されるオブジェクトの一つが共有可能なオブジェクトインスタンスではないためであり、そして、前述したように、オブジェクトが共有可能であるためには、初期オブジェクトによって参照されるオブジェクトの全てが共有可能なオブジェクトインスタンスでなければならないからである。
もし、参照されるオブジェクトが共有可能なオブジェクトインスタンスであれば(判定668のブランチ“yes”)、処理650は、分析すべき参照されるオブジェクトがさらに存在するかどうかを把握するためにチェックする。もし、参照されるオブジェクトがさらに存在すれば(判定662のブランチ“yes”)、処理650は、残りの参照されるオブジェクトの一つを選択し、そしてこれまでのように処理を進める。もし、もはや参照されたオブジェクトが存在せず(判定662のブランチ“no”)、且つ、処理がまだ終了していなければ、それは、参照されるオブジェクトの全てが分析され、そして共有可能なオブジェクトインスタンスであると判定されたことを意味する。従って、処理は、初期オブジェクトインスタンスが共有可能である旨の指示で終了する(670)。
参照されるオブジェクトが共有可能なオブジェクトインスタンスであるかどうかの判定は、再帰的になされる−すなわち、処理650は、図6の破線で示されるように、参照されるオブジェクトで再び起動されることができる。換言すれば、参照されるオブジェクトの推移的クロージャにおける各オブジェクトに関して判定がなされるように、参照されるオブジェクトが再帰的にトラバースされることができる。
もし、参照されるオブジェクトの推移的クロージャにおける全てのオブジェクトと初期オブジェクトが共有可能なオブジェクトインスタンスであれば、このオブジェクトは、共有クロージャ(shared closure)にグループ化され、そして、他のランタイムシステムで共有されることができる(例えば、共有メモリ領域に共有クロージャをコピーすることにより)。
結局のところ、処理650は、共有クロージャにおける各オブジェクトのランタイムクラスが共有可能なクラスであるかどうかを判定するものと考えることができる。前述したように、共有クロージャを共有メモリにコピーすることと共に該共有メモリからコピーすることを通じてオブジェクトが共有するところの実施例では、通常、オブジェクトは、オブジェクトの機能性と内部的な一貫性を阻害することなく、他のVMのアドレス空間への透過的ディープコピーに耐えることができれば、共有可能であると見なされる。このような実施例では、通常、クラスのオブジェクトインスタンスの直列化(serialize)又は非直列化(deserialize)において、VMが如何なるカスタムコードも実行しなければ、クラスは共有可能であると見なされる。このルールの理論的根拠は、もし、VMが如何なるカスタム直列化または非直列化コードを実行する必要がなければ、共有クロージャを共有ヒープにコピーするために(または共有ヒープからVMのアドレス空間にコピーするために)使用されるディープコピーオペレーションが、意味的に、共有クロージャにおけるオブジェクトの直列化および非直列化と等価である、ということにある。従って、もし、共有クロージャが共有ヒープにコピーされていれば、共有クロージャを自身のアドレス空間にマッピングまたはコピーする任意のVMは、オブジェクトを非直列化するために必要な追加的アクションを何ら要することなく、共有クロージャにおけるオブジェクトをアクセスすることができるべきである。
図7は、特定のクラスが共有可能なクラスであるかどうかを判定するために使用できる処理750の例のフローチャートを示す。処理750は、例えば、特定のランタイムクラスの共有可能性に関してなされる判定(654)を呼び出す場合に使用されることができる。図7に示される処理では、まず、クラス(例えば、オブジェクトインスタンスのランタイムクラス)の識別が受信される(752)。そして、クラスが共有可能かどうかを判定するために、多数の基準が適用される。具体的には、クラスは、共有可能であるためには次の条件の全てを満足しなければならない。
第1に、クラスは、直列化可能でなければならない(754)。Java(登録商標)クラスの場合、これは、クラスがマーカーインターフェイスjava(登録商標).io.Serializableを実施するかどうかをチェックすることにより判定することができる。このjava(登録商標).io.Serializableインターフェイスの実施例は、通常、クラスのオブジェクトインスタンスが有意義に他のアドレス空間にコピーされることを示す。従って、もし、クラスがjava(登録商標).io.Serializableインターフェイスを実施すれば、第1条件が満足される。
第2に、クラスは、如何なるカスタム直列化または非直列化コードも含んではならない(756)。Java(登録商標)クラスの場合、これは、クラスが次のメソッドの何れかを実施するかどうかによって判定できる。
Private void readObject(ObjectInputStream);
Private void writeObject(ObjectOutputStream);
Private void readExternal(ObjectInput);
Private void writeObject(Objectoutput);
{any access} object readResolve( );
{any access} object writeReplace( );
上述のメソッドは、直列化または非直列化の期間中に実行されるカスタムコードを構成する。このようなカスタムコードは、共有クロージャの生成中に実行されるディープコピーオペレーションと自動的に等価であることにはならない。従って、ディープオペレーションが共有クロージャを生成するために使用される場合、上述の何れかのファンクションの実施は、クラスが、処理750において共有可能なクラスと自動的に見なされることを排除する。
第3に、未解決のクラスの全てのベースクラス(base classes)は直列化可能でなければならない(758)。Java(登録商標)クラスの場合、これは、全てのベースクラスが、java(登録商標).io.Serializableを実施するか、或いは普通のデフォルトコンストラクター(default constructor)を有するかどうかをチェックすることにより判定されることができ−もしそうであれば、第3条件は満足される。もし、どのベースクラスもjava(登録商標).io.Serializableを実施しなければ、そのデフォルトコンストラクターは、非直列化の期間中に実行される。もし、デフォルトコンストラクターが普通(trivial)であれば−すなわち、もし、コンストラクターがベースクラスの普通のデフォルトコンストラクターを起動するか又は空(empty)であれば、それはデフォルトコンストラクターの再帰的検査を通じて判定されることができる−デフォルトコンストラクターの起動は、何ら非直列化に影響を及ぼさない。非通常(non-trivial)のデフォルトコンストラクターは、クラスが処理750において共有可能なクラスであると自動的に見なされることを防ぐ。なぜなら、デフォルトコンストラクターは、ディープコピーオペレーションと等価ではないカスタムコードを含んでもよいからである。
第4に、問題としているクラス(class at issue)の全てのメンバーフィールドは直列化されなければならない(760)。Java(登録商標)クラスの場合、このことは、クラスが、何らかのトランジェントフィールドまたはserialPersistentFieldsフィールドを有するかどうかをチェックすることにより判定されることができる。トランジェントフィールドは、非直列化の間にそれらのデフォルト値に設定されるフィールドである。従って、トランジェントフィールドでクラスのオブジェクトインスタンスを非直列化することは、オブジェクトインスタンスのディープコピーと等価ではない。従って、クラスにおけるトランジェントフィールドの存在は、クラスが処理750において共有可能なクラスであると自動的に見なされることを防ぐ。serialPersistentFieldsフィールドを有するクラスもまた排除される。なぜなら、このようなクラスは、トランジェントフィールドでクラスを示す他の方法であるに過ぎないからである。
第5に、クラスは、何らかのガーベッジコレクションの副次的効果(garbage collection side effects)を有しなければならない(762)。共有されるオブジェクトは、それを使用するVMのライフサイクルとは異なるライフサイクルを有してもよく、従って、VM内で実行するガーベッジコレクションアルゴリズムに影響を与えてもよい。ガーベッジコレクションの副次的効果は、クラスが処理750において共有可能なクラスであると自動的に見なされることを防ぐ。なぜなら、副次的効果は、ガーベッジコレクションアルゴリズムの適切なオペレーションを妨ぐからである。Java(登録商標)クラスの場合、処理750は、クラスが普通の終了化子(finalizer)を有することをチェックし、そしてクラスがclass java(登録商標).lang.ref.Referenceから得られたものでないことをチェックすることにより、この第3条件が満足されると判定することができる。普通の終了化子は、ベースクラスの普通の終了化子を起動する終了化子、又は空にする終了化子である。
もし、上述した5つの全ての条件が満足されれば、処理750は、問題としているクラスが共有可能なクラスであることの指示で終了する(766)。一方、もし、何れかの条件が満足されなければ、処理750は、問題としているクラスが共有可能なクラスでないことの指示で終了する(764)。
サーバー200の一実施例において、もし、自動的に適用される処理(例えば処理750)を通じてクラスが共有可能であることが分かれば、または、もし、クラスが共有可能であると予め宣言されていれば、そのクラスは共有可能である見なされる。すなわち、たとえ、自動的に適用されたクラスの分析が、そのクラスが共有可能であることを示すことができなくても、そのクラスは共有可能であるかもしれない。
もし、クラスが(例えばそのソースコードを手動で調査することにより)検査されて、そして共有に適していることが判明すれば、そのクラスは共有可能であると宣言されることができる。例えば、共有クロージャを共有メモリにコピーし、該共有メモリから共有クロージャをコピーすることを通じてオブジェクトが共有される実施例において、もし、意味検査(semantic inspection)が、上述した共有可能性基準の全ての違反が問題とならないことを立証すれば、クラスは共有に適している。共有可能性基準の違反にもかかわらず、もし、共有クロージャを共有ヒープにコピーするために(または、共有ヒープからVMのアドレス空間にコピーするために)使用されるディープコピーオペレーションが、共有クロージャにおけるオブジェクトの直列化および非直列化と意味的に等価であることが示されれば、通常、これらの違反は問題にならない。
上述した共有可能性基準を満足しないが共有には適しているクラスの一つの簡単な例は、class java(登録商標).lang.Stringである(そのクラスは、Java(登録商標)2プラットフォーム、標準版1.3において規定されている)。java(登録商標).lang.Stringクラスは、上述した第4条件に違反する。なぜなら、それは、serialPersistentFieldsフィールドを含んでいるからである。クラスにおけるコードの手動の調査は、直列化の期間中にクラスのオブジェクトインスタンスの特別な処理を実施するためにそのフィールドが含まれていることを示す。そしてそれは、直列化プロトコルの要件である。にもかかわらず、ディープコピーの効果がクラスのための直列化と等価であることが容易に示される。したがって、java(登録商標).lang.Stringクラスは、共有可能であると宣言されることができる。
上述の共有可能性基準を満たさないが共有に適した更に複雑な例は、class java(登録商標).util.Hashtable(そのクラスは、Java(登録商標)2プラットフォーム、標準版1.3で規定されている)である。java(登録商標).util.Hashtableクラスは、上述の第2および第4条件に違反する。なぜなら、それは、カスタム直列化メソッドおよびトランジェントフィールドを含むからである。そのクラスにおけるコードのレビューは、カスタム直列化メソッドとトランジェントフィールドが必要とされることを示している。なぜなら、ハッシュコード(hushcodes)は、直列化中に保存されず、それは、直列化中にハッシュテーブルにそれらのコンテンツを再構成させるからである。しかしながら、ディープコピーオペレーションはハッシュコードを保存するので、ディープコピーオペレーションは、直列化及び非直列化と等価であることが示されることが出来る。結局、class java(登録商標).util.Hashtableは、また、共有可能であると宣言されることができる。
図5に概念的に示される共有クロージャの生成および使用は、図8および図9に示される処理850および処理950により実現できる。
処理850は、共有クロージャを生成するために使用できる処理の例を示す。処理850において、第1のランタイムシステム(例えば、VM)における初期オブジェクトの識別が受信される(852)。そして、共有クロージャ−すなわち、初期オブジェクトによって参照される全てのオブジェクトの推移的クロージャと初期オブジェクト−が識別され(854)、そして共有クロージャが他のランタイムシステム(例えば、他のVM)によって共有され、または他のランタイムシステムで使用されることができるかどうかに関して判定がなされる(856)。この判定は、例えば、共有クロージャにおけるオブジェクトが共有可能であるかどうかを判定することにより(あるいは、より正確には、共有クロージャにおける各オブジェクトインスタンスが共有可能なオブジェクトインスタンスであるかどうかを判定することにより)、行われる。一実施例において、共有クロージャを識別し、そして共有クロージャにおけるオブジェクトが共有可能なオブジェクトインスタンスであるかどうかを判定する(854,856)ためのオペレーションは、図6に示される処理650によって実施される。
もし、共有クロージャが他のランタイムシステムにおいて使用可能でなければ(判定858のブランチ“no”)、処理850は、例外(exception)を引き起こし、または、或るタイプの否定的な指示を発生させる。例えば、もし、共有クロージャにおけるオブジェクトが全て共有可能なオブジェクトインスタンスでなければ、処理は、初期オブジェクトとその共有クロージャが共有可能でないことを示す例外を引き起こす。
もし、共有クロージャが他のランタイムシステムにおいて使用可能であれば(判定858のブランチ“yes”)、処理850は、共有クロージャを他のランタイムシステムに利用可能とするためのメカニズムを起動する。例えば、もし、オブジェクトが共有メモリの使用を通じて共有されれば、共有クロージャは、共有メモリ領域にコピーされることができる(862)。他の実施例において、共有クロージャは、メッセージまたは他の通信手段の使用を通じて1又は2以上のランタイムシステム(例えば、他のVM)に伝送されることができる。
また、共有クロージャを生成する処理は、特定のネーム(name)または他の識別子(identifier)を共有クロージャに関連づけることができる(864)。その後、このような識別子は、アクセスされるべき共有クロージャを識別するために他のランタイムシステムによって使用されることができる。
いくつかの実施例では、また、共有クロージャを生成する処理は、バージョニング(versioning)の使用を起動する。処理850において、バージョニングは、共有メモリに格納された共有クロージャに関連づけられたバージョンナンバー(version numbers)の使用を通じて行われる。共有クロージャが所定のネームで生成されれば、そのネームを有する共有クロージャが共有メモリに既に存在するかどうかに関して判定がなされる。もし、このようなクロージャが存在すれば(判定866のブランチ“yes”)、共有クロージャに関連する現在のバージョンナンバーが増加され(868)、そして新たな現在のバージョンナンバーが、新たに生成された共有クロージャと関連づけられる(872)。もし、共有メモリに所定のネームを有する共有クロージャが存在しなければ(判定866のブランチ“no”)、新たな共有クロージャのための現在のバージョンナンバーは、最初のバージョンを示すナンバー(例えば、0または1)に設定され(870)、そして、新たに生成された共有クロージャと関連づけられる(872)。
バージョニングは、共有クロージャを更新するために使用されることができる−例えば、共有クロージャの新たな更新されたバージョンは、共有クロージャに対して前に与えられたネームと同一のネームで生成されることができる。一実施例において、ネームが付された新たなバージョンの共有クロージャが生成された場合、この新たなネームが付された共有クロージャをVMに関連づけるためのその後の全てのオペレーションは、新たなバージョンの共有クロージャを使用する。既に共有クロージャをアクセスしているVM(例えば、それらのアドレス空間にマッピングされた共有クロージャの前のバージョンを有するVM)は、新たなバージョンに影響されない−それらは、単に、古いバージョンに対する全てのオブジェクト参照を保持する。この実施例では、複数のバージョンの共有クロージャは、もはや古いバージョンが如何なるVMにも参照されなくなるまで、共有メモリに共存することができ、従ってガーベッジコレクションが行われることができる。
図9は、共有クロージャをアクセスし使用するための処理例のフローチャートを示す。処理950において、ネーム又は他の識別子が受信され(952)、そして、関連する共有クロージャを識別するために使用される(954)。上記ネーム又は他の識別子は、共有クロージャが生成されたときに該共有クロージャに関連づけられた識別子に対応する(例えば処理850のオペレーション864)。バージョニングが実施される場合、もし、2以上のバージョンの特定の共有クロージャが存在すれば、ごく最近生成されたバージョンの特定の共有クロージャが識別される。
そして、識別された共有クロージャは、ランタイムシステム(例えば、VM)と関連づけられる(956)。一実施例において、共有クロージャは、次の2つのうちの一つの方法によりランタイムシステムと関連づけられることができる−一つは、共有メモリ領域からランタイムシステムのアドレス空間に共有クロージャをマッピングすることであり、もう一つは、共有メモリ領域からランタイムシステムのアドレス空間に共有クロージャをコピーすることである。共有クロージャがランタイムシステムと関連づけられた後、共有クロージャ内のオブジェクトは、通常のオペレーション(例えば、通常のJava(登録商標)オペレーション)を用いてアクセスされることができる(962)。
いくつかの実施例では、共有クロージャにおけるオブジェクトへのアクセスは、この共有クロージャがランタイムシステムにどのように関連づけられているかに依存してもよい。例えば、一実施例において、もし、共有クロージャがVMのアドレス空間にマッピングされれば(判定958のブランチ“mapped”)、共有クロージャにおけるオブジェクトへのアクセスは、リードのみのアクセスに制限される(960)。この制限のため、共有クロージャにおける多くのオブジェクトインスタンスに対するライトの試行はエラーに終わるであろう。この制限は、共有オブジェクトインスタンスにおける参照ナンバー変数をVMのプライベートヒープへの参照でオーバーライトすることにより、或いは逆に、共有オブジェクトの機能性または内部的一貫性をブレークすることにより、VMが共有オブジェクトインスタンスを“ブレーク(brake)”することを防止するのに有用である。
他方、もし、共有クロージャがVMのアドレス空間にコピーされれば(判定958のブランチ“copied”)、VMは、コピーされたオブジェクトに対する完全なリード−ライトが認められる。このような実施例では、従って、共有クロージャにおけるオブジェクトは、共有クロージャをVMのアドレス空間にコピーし、共有クロージャにおけるオブジェクトのコンテンツを修正し、そして、共有メモリにおける新たなバージョンの共有クロージャを生成することにより(例えば、図8に示される処理850を用いて)更新されることができる。
他のアプローチは、共有クロージャをランタイムシステムと関連づけるために使用されることができ、そして、ランタイムシステムから共有クロージャにおけるオブジェクトに対するアクセスを提供するために使用されることができる。例えば、コピーオンデマンドアプローチ(copy-on-demand approach)が使用されることができる。このような一実施例では、共有クロージャは、共有クロージャへのアクセスをリードのみのアクセスに制限することなくVMのアドレス空間にマッピングされる。その代わり、共有クロージャへのアクセスはモニターされ、そして、共有クロージャに対する最初の試行ライトアクセスを検出すると、すぐに、共有クロージャは、VMのアドレス空間にコピーされ、これにより、マッピングされた共有クロージャからコピーされた共有クロージャに共有クロージャを伝送する。そして、試行ライトアクセスは、完了することを許され、そしてその後、コピーされた共有クロージャに対するリード及びライトアクセスが通常どおり続行する。もし、マッピングされた共有クロージャから、コピーされた共有クロージャへの伝送が発生したときに、共有クロージャのヒープアドレスが変化すれば、ヒープに対する既存の参照が、新たに生成された共有クロージャのコピーにリダイレクト(redirect)されなければならない。或いは、基礎をなすOS特性(underlying OS feature)は、ヒープアドレスが変化することなくOSがコピーオンデマンド機能性を提供することを可能にする方法で、共有クロージャをマッピングするために使用されることができる。
共有クロージャを生成し、マッピングし、コピーするための機能に加えて、API(Application Programming Interface)は、共有オブジェクトを管理するための追加的機能を含むことができる。例えば、APIは、また、“デリート(delete)”機能を含むこともできる。“デリート”機能の一実施例は、ネーム又は他の識別子を入力パラメータと見なし、そして共有メモリにおける関連する共有クロージャを、デリートされたものとしてマークする。デリートされたものとして共有クロージャをマークすることは、共有クロージャを既にアクセスしているVMに影響を与えないが、その後に(例えば、共有クロージャをそれらのアドレス空間にマッピングまたはコピーすることにより)共有クロージャをアクセスしようとするVMは、そうすることを阻止される。
共有クロージャがVMのアドレス空間にマッピングされることができるサーバー200の実施例では、デリートされた又は古いバージョンの共有クロージャのためのガーベッジコレクションは、アドレス空間に共有クロージャがマッピングされたVMの数の経過を追うことにより実施されることができる。VMが共有クロージャをそのアドレス空間にマッピングする度にカウントがインクリメントされることができる。自身のガーベッジコレクションの最中に、VMが、もはやそれが前にマッピングされた共有クロージャへの参照を何ら含んでいないと判定したときに、そのカウントはデクリメントされることができる。特定の共有クロージャと関連する上記カウントがゼロに到達すると、その共有クロージャは共有メモリからデリートされることができる。
Java(登録商標)では、オブジェクトインスタンスは、通常、オブジェクトインスタンスのクラスのランタイム表現に対する参照を含み、そしてクラスランタイム表現は、クラス用のクラスローダーに対する参照を含む。従って、Java(登録商標)オブジェクトインスタンスに関連するクラスローダー及びランタイム表現は、オブジェクトインスタンスの共有クロージャに含まれ、そのことは、オブジェクトインスタンスが共有可能であるためには、ランタイム表現及びクラスローダーが、それ自体、共有可能でなければならないことを意味する。従って、クラスランタイム表現とクラスローダーを含むサーバーの実施例では、二つの追加的基準が、特定のクラスが共有可能であるかどうかを判定するために使用されることができる:クラスは、共有可能なランタイム表現と共有可能なクラスローダーを備えるべきである。
種々の技術が、クラスランタイム表現及びクラスローダーを取り扱うために(すなわち、クラスランタイム表現およびクラスローダーを“共有可能”とするために)使用されることができる。一つの技術として、クラスランタイム表現とクラスローダーを実際に共有することが挙げられる。すなわち、オブジェクトインスタンスが共有メモリにコピーされたときに、オブジェクトインスタンスのクラスに対応するクラスローダーとランタイム表現は、また、全てのVMによってアクセスされることができるように、共有メモリにコピーされる(例えば、オペレーションをマッピングすることを通じて)。この技術の種々の最適化が可能である。例えば、クラスのランタイム表現を共有メモリにコピーする前に、共有メモリは、そのクラスのためのランタイム表現が既に共有メモリに存在しているかどうかを判定するためにチェックされることができ−もし、そうであるならば、共有メモリにコピーされているオブジェクトインスタンスにおけるランタイム表現に対する参照は、単純に、既に共有メモリに存在するランタイム表現を参照するように設定されることができる。
ランタイム表現及びクラスローダーを取り扱うための第2の技術は、それらを共有するためではなく、それらが、各VMにおける固定場所に位置されることを確実にするためである。換言すれば、各クラスのためのクラスローダー及びランタイム表現は、各VMにおいて同一の固定されたアドレスに位置されなければならない。そして、各オブジェクトインスタンスにおけるランタイム表現は、オブジェクトインスタンスのクラスのためのランタイム表現に対応する場所に設定されることができる。このアプローチを用いれば、ランタイム表現に対する参照は、オブジェクトインスタンスが共有メモリからマッピングされたか、または、アドレス空間にコピーされたかどうかとは関係なく、有効(valid)である。
しかしながら、各クラスのためのランタイム表現の場所を固定することは、実際的ではないかもしれない。従って、ランタイム表現及びクラスローダーを取り扱うための第3の技術は、オブジェクトインスタンスがVMにコピーされたときに各オブジェクトインスタンスのためのランタイム表現に対する参照を調整することである。従前の技術と同様に、ランタイム表現及びクラスローダーはこの技術で共有される−すなわち、各VMは、各クラスのためのそれ自身のクラスローダー及びランタイム表現を格納する。しかしながら、従前の技術とは違って、この技術は、各ランタイム表現及びクラスローダーの場所が各VMにおいて固定されることを要しない。その代わり、クラスローダー及びランタイム表現の場所は、各VMにおいて異なることができる。オブジェクトインスタンスが特定のVMにコピーされると、適切なクラスランタイム表現の場所が決定され、そして、オブジェクトインスタンスにおける対応参照がその場所に設定される。
ランタイム表現を取り扱うための第3の技術―各VMにおけるランタイム表現に対する参照を調整すること−は、オブジェクトインスタンスが、多数のVMに同時にマッピングされることを阻止する。この理由は、前述したように、共有されたオブジェクトインスタンスは、如何なるプライベートヒープへの参照も有することができないためである。この第3の技術は、各VMにおけるプライベートランタイム表現を参照するための参照を調整するので、この技術は、オブジェクトがVMのアドレス空間にコピーされるとき、あるいは、オブジェクトが1回に一つのVMによってのみアクセスされる他の環境において(例えば、オブジェクトインスタンスが一つのVMにマッピングされるときに他のVMがそのオブジェクトインスタンスをマッピングしないように、オブジェクトインスタンスが“排他的に”マッピングされることができる環境において)のみ使用されることができる。
上述の第3の技術は、VMが多数の物理マシン上で実行されることができるところのクラスターアーキテクチャにおいて有用である。ランタイム表現は、通常、物理マシン間で共有されず、したがってランタイム表現に対する参照は、オブジェクトインスタンスが物理マシン間で共有されるときに(例えば、一つの物理マシン上のVMにおいて使用されているオブジェクトインスタンスが、そのマシン上のVMにおいて使用されるべき第2の物理マシンに伝送されるときに)調整されなければならない。
図10は、多数のマシン間でオブジェクトを使用するための技術を示す。この技術は、上述したランタイム表現を取り扱うための第3の技術の一般化されたバージョンであり、ソースランタイムシステムで実行されることができる幾つかのオペレーションと、ターゲットランタイムシステムで実行されることができる幾つかのオペレーションとの組み合わせを含む。図10において、処理1000は、ソースランタイムシステムにおいて実行されることができるオペレーションの例を示し、処理1050は、ターゲットランタイムシステムにおいて実行されることができるオペレーションの例を示す。通常、この技術は、オンザフライでのスタブ(stubs)の生成および使用を含む−ランタイムメタデータに対する参照は、ソースランタイムシステムにおけるプロキシで置き換えられ、そしてプロキシは、ターゲットランタイムシステムにおけるランタイムメタデータに対する参照で置き換えられる。
さらに詳しくは、処理1000において、ターゲットランタイムシステムにおいて使用され又は共有されるべき一組のオブジェクトは、最初に、ソースランタイムシステムにおいて識別される(1002)。このオペレーションは、例えば、図6の処理650のように、ソースランタイムシステムにおけるオブジェクトの共有クロージャの識別と、共有クロージャにおける全てのオブジェクトが共有可能なオブジェクトインスタンスであることの検証を起動する。しかしながら、このオペレーションは、また、非常にシンプルである−例えば、単一のオブジェクトが、ターゲットランタイムシステムにおいて使用されるために選択されることができる。(しかしながら、単一のオブジェクトが選択された場合、例えば参照されるオブジェクトを両方のランタイムシステムにおいて同一アドレスに配置することにより、または、上述したように、選択されたオブジェクトにおける参照を調整することにより、特別な処理(arrangement)が行われなければ、ソースランタイムシステムにおける1又は2以上の参照されるオブジェクトに対する選択されたオブジェクトにおける何れの参照もターゲットランタイムシステムにおいて有効ではない。)
そして、識別された一組のオブジェクトにおけるオブジェクトがトラバースされる。もし、一組のオブジェクトにさらにオブジェクトが存在すれば(判定1004のブランチ“yes”)、次のオブジェクトが読み出され(1006)、そして、ランタイムメタデータに対するオブジェクトにおける任意の参照(例えば、オブジェクトのクラスのランタイム表現に対する参照)がプロキシで置き換えられる(1008)。全てのオブジェクトがトラバースされた後(判定1004のブランチ“no”)、一組のオブジェクトが、ターゲットランタイムシステムに送られる(1010)。もちろん、処理1000におけるオペレーションは、別のシーケンスで実行されることが可能である−例えば、プロキシがオブジェクトに配置され、そしてこのオブジェクトは、一組のオブジェクト全体が識別される前に、ターゲットランタイムシステムに送られることができる。このようなオペレーションは、例えば、共有クロージャを識別する再帰的処理の一部としてオンザフライで実行されることができる。
処理1050は、ターゲットランタイムシステムにおいて(例えば、ソースVMとは異なるマシン上で実行するターゲットVMにおいて)使用されることができる対応処理を示す。一組のデータオブジェクトが受信され(1052)、そして、ターゲットランタイムシステムにおいてコピーされる(1054)。そして、受信されたオブジェクトの組の中のオブジェクトがトラバースされる。もし、受信されたオブジェクトの組に更なるオブジェクトが存在すれば(判定1056のブランチ“yes”)、次のオブジェクトが受信される(1058)。そして、オブジェクトに対応する関連ランタイム情報(relevant runtime information)が識別される(1060)。このような情報は、例えば、オブジェクトのランタイムクラスを含むことができる。そして、このオブジェクトのプロキシは、上記ランタイム情報に基づいてターゲットランタイムシステムにおけるランタイムメタデータに対する参照で置き換えられることができる。例えば、一旦、オブジェクトのランタイムクラスが識別されると、このオブジェクトにおけるランタイム表現のためのプロキシは、ターゲットランタイムシステムにおけるクラスのランタイム表現に対する参照で置き換えられることができる。
或る環境では、オブジェクトにおける1又は2以上のプロキシがターゲットランタイムシステムにおけるランタイムメタデータに対する参照で置き換えられる前に、まず、このようなメタデータがターゲットランタイムシステムにロードされたかどうかを判定するためにチェックが行われる。もし、メタデータがターゲットランタイムシステムにロードされていなければ(判定1062のブランチ“no”)、メタデータは必要に応じてロードされることができる(1064)。一例として、クラスローダーは、プロキシがそのランタイム表現に対する参照で置き換えられる前にVMにクラスのランタイム表現をロードするために起動されることができる。
処理1000と同様に、処理1050におけるオペレーションは、別のシーケンスで実行されることができる−例えば、プロキシは、オブジェクトが受信されたときに(すなわち、一組のオブジェクトの全体が受信される前に)ランタイムメタデータに対する参照で置き換えられることができる。更なるバージョンもまた可能である。例えば、プロキシは、オブジェクトが受信されたとき、または、“オンデマンド(on demand)”ベースで(例えば、オブジェクトが最初にターゲットランタイムシステムにおいてアクセスされたとき)、ランタイムメタデータに対する参照で置き換えられることができる。
共有クロージャの生成および使用と、ランタイムメタデータに対する参照の取り扱いを含む上述の技術は、ひとつのランタイムシステムにおける複合データ構造を分解し、他のランタイムシステムの本来のフォーマットでデータ構造を再構成する一般的概念の特別な実施例である。本技術は、例えば、サーバー環境においてオブジェクトを共有するために使用されることができ、その環境では、複合データ構造はヒープ(または、ヒープ内の一組のオブジェクトのような、その一部)であり、ランタイムシステムはVMである。上述の技術のこのような使用例は、以下に更に詳細に説明される。
図11は、サーバーにおける共有オブジェクトを使用するための処理1150の例のフローチャートである。処理1150は、共有オブジェクトが、処理取り付け可能なVMとともにどのように使用されることができるかを示している。処理1150において、VMは、ユーザーセッションのために生成され(1152)、そしてオブジェクトの共有クロージャが生成され、そして共有メモリに格納される(1154)。サーバーがユーザーセッションに対応するユーザーリクエストを受信すると(1156)、それは、サーバーに割り当てられた処理のプールから利用可能な処理を選択し(1158)、そして、ユーザーセッションのために生成されたVMを、選択された処理にバインドする(1160)。
もし、VMが共有クロージャにおけるオブジェクトをアクセスする必要がなければ(判定1162のブランチ“no”)、VMは、単にそのリクエストを処理することができ(1164)、その後、VMは、その処理からバインド解除されることができる(1166)。そして、処理は、利用可能な処理のプールに戻されることができ、そしてそのサーバーは、新たなリクエストを受信したときに、再びVMを処理にバインドすることができる(1156)。
一方、もし、VMが共有クロージャにおけるオブジェクトをアクセスする必要があれば(判定1162のブランチ“yes”)、共有クロージャはVMと関連づけられる。共有クロージャは、種々の方法でVMと関連づけられることができる−例えば、共有クロージャは、共有クロージャを、選択された処理のアドレス空間にマッピングまたはコピーすることにより、選択された処理にバインドされることができる。
共有クロージャがVMと関連づけられる的確な方法は、VMによって必要とされるアクセスのタイプに依存する。上述したように、一つのサーバー実施例では、他のVMにおいて有効でない値にメンバー変数を設定することにより、マッピングVMが共有クロージャにおける共有オブジェクトインスタンスをブレークすることを防止するために、マッピングされた共有クロージャは、常にリードのみのアクセスに制限される。このような実施例では、もし、処理1150においてユーザーセッションに関連するVMが、オブジェクトに対するリードアクセスだけが必要ならば(すなわち、判定1168のブランチ“no”によって示されるように、もし、VMが、共有クロージャにおけるオブジェクトの何れをも修正する必要がないのであれば)、共有オブジェクトは、選択された処理のアドレス空間にマッピングされることができる(1170)。そして、VMは、リクエストを処理し(1164)、必要に応じて共有オブジェクトから情報を読み出す。
もし、VMが共有オブジェクトに対するリードライトアクセスを必要とすれば(すなわち、判定1168のブランチ“yes”で示されるように、もし、VMが1又は2以上のオブジェクトを修正する必要があれば)、共有クロージャは、選択された処理のアドレス空間にコピーされる(1172)。そして、VMは、共有オブジェクトに対する完全なリードライトアクセスを有し、そしてそれは必要に応じてオブジェクトを修正し、リクエストを処理することができる。VMが共有オブジェクトの修正を終了すると、それは、共有クロージャを共有メモリにコピーすることができる(1176)。上述のように、一つのサーバー実施例では、共有クロージャは、共有クロージャを再生成することにより(例えば、“生成(create)”機能を起動し、前に使用された同じネームを共有クロージャに割り当て、そしてそのネームを有する共有クロージャの古いバージョンが依然として共有メモリに存在すれば新たなバージョンの共有クロージャを生成することにより)、共有メモリにコピーされることができる。これまでのように、リクエストが処理された後は、VMは処理からバインド解除されることができ(1166)、処理は、利用可能な処理のプールに戻されることができ、そして、サーバーは、新たなリクエストを受信するために再び待機することができる(1156)。
共有クロージャにおけるオブジェクトは、以下の例に示すように、ユーザーコンテキスト情報を含んで、任意のタイプのオブジェクトを含むことができる。さらに、処理1150は、共有クロージャをアクセスする一つのVMを示しているだけではあるが、共有クロージャは、また、他のVMによってアクセスされることもできる(例えば、他のVMは、共有クロージャをマッピングまたはコピーすることができ、これにより共有クロージャにおけるオブジェクトをアクセスする)。
共有仮想マシン(Shared Virtual Machines)
図2および3に示されるサーバー実施例は、ユーザーセッションが大規模なユーザーコンテキストに対応する環境に良好に適合する。しかしながら、このような実施例は、ユーザーコンテキストが相当に小さい環境(例えば、ユーザーコンテキストがそれぞれ10キロバイトよりも小さい環境)では最適でないかもしれない。VM間でオブジェクトを共有する能力があるとしても、このような環境において各ユーザーセッションに個別のVMを割り当てることは、ユーザーセッションごとに大きなオーバーヘッドを招くので、実際的ではないかもしれない。
図12は、ユーザーコンテキストが相当に小さいと予想される環境において、より実用的なサーバー200の別の実施例を示す。各ユーザーセッションのために一つのVMを生成する代わりに、図12に示されるサーバー200の実施例は、共有されたVM(例えば、VM301,303,305,307,309)のプール300を使用する。サーバー200は、各ユーザーセッションのためのユーザーコンテキスト(例えば、ユーザーコンテキスト501,503,505,507,509,511,513,515,519)を生成する。ユーザーコンテキストは、VMのプール300におけるVMがそうであるように、共有メモリ領域255に格納される。前述した実施例と同様に、サーバー200は、ワーク処理(例えば、ワーク処理401,403,404,409)のプール400、および配信処理410を使用する。
オペレーションにおいて、図12に示されるサーバー200の実施例は次のように動作する。サーバー200がユーザーリクエストを受信すると、配信処理410は、ワーク処理のプール400から利用可能なワーク処理(例えば、ワーク処理404)を選択し、そしてユーザーリクエストを、選択されたワーク処理404に配信する。そして、ワーク処理404は、VMのプール300から利用可能なVM(例えば、VM305)を選択する。選択されたVM305は、例えば、共有メモリ255から、選択されたワーク処理404のアドレス空間にVM305をマッピングすることにより、選択されたワーク処理404にバインドされる。
次に、ワーク処理404は、ユーザーリクエストに対応するユーザーセッションと、関連するユーザーコンテキスト(例えば、ユーザーコンテキスト501)とを識別する。そして、識別されたユーザーコンテキスト501は、例えば、共有メモリ領域255からワーク処理404のアドレス空間にユーザーコンテキスト501をコピーすることにより、ワーク処理404にバインドされる。いまや、ユーザーリクエストは、ユーザーコンテキスト501に関連してワーク処理404においてVM305を実行することにより処理されることができる。
関連するユーザーコンテキストを識別し、そしてそのコンテキストを選択されたVMに関連づけるための他の実施例が可能である。例えば、配信処理410は、関連するユーザーコンテキストを識別し、そしてそのコンテキストを識別する情報を、選択されたVMに受け渡すことができ、そして、ユーザーコンテキスト(例えば、そのコンテキストを作り出したオブジェクトの共有クロージャ)は、選択されたVMに代わって、選択されたワーク処理のアドレス空間にマッピングまたはコピーされることができる。概念的には、これは、識別されたユーザーコンテキストが選択されたVMにプラグインされ、そして選択されたVMが選択されたワーク処理にプラグインされるというシーケンスとして考えることができ、技術的な観点からは、この概念的シーケンスは、識別されたユーザーコンテキストと選択されたVMを表す共有メモリのセクションを、選択されたワーク処理のアドレス空間に単にマッピングまたはコピーすることにより実行されることができる。
リクエストが処理されると、VM305とユーザーコンテキスト501は、(例えば、ワーク処理404からVM305をマッピング解除し、そしてユーザーコンテキスト501を共有メモリ領域255にコピーし直すことにより)ワーク処理404からバインド解除される。そして、VM305およびワーク処理404は、再び利用可能であるようにマークされ、そしてそれらは、サーバー200によって受信された追加のリクエストを処理するために使用されることができる。もちろん、VM305とワーク処理404は、新たなリクエストの処理において共に対にされなくてもよい−例えば、もし、新たなリクエストがワーク処理404に配信され、且つVM305が他のリクエストの処理で忙しければ、ワーク処理404は、VMのプール300から他のVMを選択しなければならない(または、VMのプール300におけるVMが利用可能になるのを待つ)。
この方法では、図12に示されるサーバー実施例におけるVMは共有されるが(すなわち、サーバーは、ユーザーセッションごとに一つのVMを割り当てない)、各VMが一回で一つのユーザーセッションのみに専念するので、互いに分離されている。さらに、各VMは、分離された処理において動作するので、もし、VMがクラッシュすれば、このようなクラッシュは、(オペレーティングシステムが互いから処理をどの程度良好に分離しているかに依存して)クラッシュしたVMにおいて処理されていたリクエストに対応するユーザーセッションにしか影響を与えない。従って、共有されながらも専用化されるVMのプールを使用することの上記アプローチは堅牢なサーバーをもたらすが、前述した実施例よりもオーバーヘッドが少ない。
VMが各ユーザーセッションに割り当てられるサーバー実施例において、種々の最適化が同一の利益−オーバーヘッドの低減−を達成するために使用されることができる。例えば、対応するユーザーセッションの終わりでVMを終了させる代わりに、VMは再使用されることができる。すなわち、VMは別のユーザーセッションに関連づけられ、そして新たなユーザーセッションに対応するリクエストを処理するために使用されることができる。有用ではあるが、にもかかわらず、このアプローチは、サーバーが各ユーザーセッションのために少なくとも一つのVMを例示化する必要があるので、多数の同時的ユーザーセッションが存在する場合には依然として大きなオーバーヘッドを必要とする。
一方、図12に示されるサーバー実施例は、どんなに多くのVMがVMプール300に割り当てられても、VMの数を制限する。前述したように、この実施例は、多くの同時的ユーザーセッションと小さなユーザーコンテキストを有する環境に良好に適合する。このような環境は、通常、数式P<=V<<Uにより特徴づけられる。ここで、Pはワーク処理400のプールに割り付けられたワーク処理の数であり、Vは、VMのプールに割り付けられたVMの数であり、Uは、サーバーによって処理されているユーザーセッションの数である。この数式の左部分は、VMのプールに割り付けられたVMの数が通常ワーク処理のプールにおけるワーク処理の数に等しいかこれよりも大きくなければならないことを示している(そうでなければ、全てのVMが使用されているときでさえ、幾つかの待機状態(idle)の使用されない処理が存在するからである)。上記数式の右部分は、VMの数が、ユーザーセッションの数よりも十分に小さいことを示している。繰り返すが、このようなことは可能である。なぜなら、同時ではないにしても各VMは異なるユーザーによって共有可能であるからである。
図12に示されるサーバー200の実施例は、VM間でのオブジェクトの共有により可能とされる。図3に示されるサーバー実施例では、各ユーザーコンテキスト(例えば、ユーザーコンテキスト301)は、ユーザーセッションに対応する寿命期間の間、一つのVM(例えば、VM501)と関連づけられ、そしてそのユーザーコンテキストとその関連づけられたVMは、対応するユーザーセッションからユーザーリクエストが受信されたときに、両方ともワーク処理にマッピングされる。従って、図3における実施例では、各VMは、一つのユーザーセッションと関連づけられ、そしてVMは、上記関連づけられたユーザーコンテキストをアクセスすることしかできない−VMが他のセッションに対応するユーザーコンテキストをアクセスすることは可能ではない。例えば、VM301は、ユーザーコンテキスト501をアクセスすることしかできず、そしてVM303は、ユーザーコンテキスト503をアクセスすることしかできない。従って、各VMは、その関連づけられたユーザーコンテキストに対応するリクエストを処理することしかできない。
しかしながら、上述の共有化技術は、ユーザーコンテキストを作成するオブジェクトを含んで、VMがオブジェクトを共有することを可能にする。例えば、ユーザーコンテキストは、共有クロージャとして共有メモリヒープに格納されることができる。そして、共有クロージャ−以下、ユーザーコンテキスト−は、多数のVMによってアクセスされることができる。
従って、図12に示されるサーバー実施例は、次のように説明される:第1に、VM及びユーザーコンテキストは互いに分離され;第2に、ユーザーコンテキストは、VMプールにおける全てのVMによってアクセスできる共有メモリヒープに格納され;最後に、ユーザーリクエストは、対応するユーザーコンテキストと利用可能なVMとを利用可能なワーク処理にマッピングすることにより処理される。
上述の構想(scheme)が図13に概念的に示されている。図3と同様に、図13におけるVMとユーザーコンテキストは、共有メモリ領域255に格納される。しかしながら、図3と異なり、図13におけるVMは、もはや特定のユーザーコンテキストと関連づけられない−任意の利用可能なVMが任意のユーザーコンテキストと連動することができる。例えば、図3において、VM301は、その関連するユーザーコンテキスト501と連動することしかできない。これに対し、図13では、VMは、共有メモリにおける任意のユーザーコンテキスト、例えば、ユーザーコンテキスト519と連動することができる。
幾つかの実施例では、一旦、VMがユーザーコンテキストと対にされると、そのVMは、対応するユーザーコンテキストが処理されるまで、そのユーザーコンテキストと対にされたままでなければならない。特に、たとえVMが、現在、現在のユーザーリクエストの処理において(例えば、I/Oイベントを待っているために)ブロックされているとしても、そのVMは、利用可能なものとしてマークされることはできず、且つ、他のユーザーリクエストを処理するために使用されることはできない。
例えば、Java(登録商標)実施例では、リクエストが処理されている間に、(ユーザーヒープとユーザースタックを含む)ユーザーコンテキストから(VMヒープとVMスタックを含む)VMを分離することは容易ではない。なぜなら、VMスタックは、ユーザースタックと混ざっているからである。従って、VMは、対応するリクエストが処理されてユーザースタックが空になるまで、ユーザーコンテキストと対にされたままでいなければならない。
図14は、上述の構想に対応するユーザーコンテキストとVMを対にする方法(pairing)を示す。サーバーがユーザーコンテキスト501に対応するリクエストを受信する前に、ユーザーコンテキスト501は共有メモリに格納され、そしてVM301は、任意のユーザーコンテキストに対応するリクエストを処理するために利用可能である。ユーザーコンテキスト501に対応するリクエストが受信されたとき(1402)、ユーザーコンテキスト501とVM301は、両方とも、ワーク処理401にバインドされる。従って、ユーザーコンテキスト501とVM301は、VMがユーザーコンテキスト501と共にワーク処理401において動作するように互いに対にされる。
リクエストの処理における或る時点で、VMにおける全てのスレッドまたはコルーチンは、(例えば、もし、それら全てが、I/Oイベントの完了を待っていれば)ブロックしてもよい。それが起これば(1404)、VM301とユーザーコンテキスト501は、ワーク処理401からバインド解除され、これにより、他のリクエストに取りかかるためにワーク処理401を開放する。しかしながら、VM301は、利用可能なものとしてマークされない−それは、ユーザーコンテキスト501と対にされたままとされ、そして、少なくとも一つのスレッドが再び動作するまで(例えば、指示されたI/Oイベントが完了したとき)アイドル状態(idle)を保つ。それが起これば(1406)、VM301とユーザーコンテキスト501は、そのVMがそのユーザーコンテキストと共に実行を継続するよう、ワーク処理に再びバインドされることができる。VM301とユーザーコンテキスト501は、それらが前にバインドされた同じワーク処理401にバインドされなくてもよい−例えば、もし、他のVMが、現在、ワーク処理401にバインドされていれば、VM301とユーザーコンテキスト501は、利用可能な他のワーク処理にバインドされる。
最後に、リクエストが処理されて応答(response)が送られると(1408)、VM301とユーザーコンテキスト501は、ワーク処理からバインド解除される。ユーザーコンテキスト501は、共有メモリに再び格納され、そしてVM301とワーク処理は、両方とも、他のリクエストに取りかかるために利用可能なものとしてマークされる。
図15は、図12に示されるサーバー実施例においてリクエストを処理するための処理1550の例を示すフローチャートである。処理1550において、オペレーティングシステムのプールとVMのプールは、最初に初期化される(1552)。ユーザーコンテキストは、各ユーザーセッションのために生成され、そしてサーバーの共有メモリ領域に格納される(1554)。各ユーザーコンテキストは、例えば、オブジェクトの共有クロージャとして格納されることができる。
サーバーがユーザーセッションからリクエストを受信すると(1556)、それは、対応するユーザーコンテキストを識別し(1558)、そして、ワーク処理のプールから利用可能な処理を選択すると共に(1560)、VMのプールから利用可能なVMを選択する(1562)。そして、選択されたVMは、(例えば、共有メモリ領域からのVMを、選択された処理のアドレス空間にマッピングすることにより)選択された処理にバインドされる(1564)。VMがリクエストを処理するために使用される前に、ユーザーコンテキストはVMと関連づけられなければならない(1566)。これは、例えば、ユーザーコンテキストを選択された処理にバインドすることにより行われることができる。上述したように、一実施例において、共有クロージャにおけるオブジェクトへのアクセスは、もし、共有クロージャが処理にコピーされていれば制限されないが、しかし、もし、共有クロージャがその処理にマッピングされていれば、リードのみのアクセスに制限される。このような実施例では、VMはリクエストの処理中にユーザーコンテキストを修正する必要があり得るので、ユーザーコンテキストは、処理にマッピングされるというよりは、むしろコピーされる。しかしながら、他の実施例が可能である−例えば、ユーザーコンテキストが処理にマッピングされ、マッピング処理におけるVMがそれらのオブジェクトを使用し或いは修正する間に他の処理またはVMがユーザーコンテキストにおけるオブジェクトをアクセスすることを防ぐようにロッキング変数(locking variable)が設定されることができる。ユーザーコンテキストに処理排他的アクセスと選択されたVMとを与えるための追加的バリエーションが可能である。
一旦、選択されたVMが選択された処理にバインドされ、そしてユーザーコンテキストがそのVMと関連づけられると、リクエストは、ユーザーコンテキストと共に処理におけるVMを実行することにより実行されることができる。上述したように、一実施例において、もし、VMがブロックし、或る理由で処理を継続することができなくなれば(例えば、もし、VMがI/Oの発生を待っていれば)、VMはワーク処理からバインド解除されることができる。そして、ワーク処理は、利用可能なものとしてマークされ、他のリクエストに取りかかるために使用されることができる。また、もし、ユーザーリクエストの処理が完了されるまでにユーザーコンテキストからVMを分離することが可能でなければ、VMは、利用可能なものとしてマークされ、そして他のリクエストを処理するために使用されることができる。後者のシナリオでは、VMは、ユーザーコンテキストと対にされたままでなければならない。もはやVMがブロックされなければ、VMとユーザーコンテキストは、利用可能なワーク処理に再びバインドされることができ、そして、VMは、ユーザーリクエストの処理を続けることができる。
ユーザーリクエストが処理されたとき、VMをワーク処理にバインドし、ユーザーコンテキストをVMと関連づけるオペレーションが用意されることができる−例えば、ユーザーコンテキストは、VMから分離されることができ(1570)、そしてVMは、ワーク処理からバンドが解除されることができる(1572)。ユーザーコンテキストがVMから分離される方法は、ユーザーコンテキストがVMと関連づけられる方法に依存する。上述したように、一実施例において、ユーザーコンテキストは、VMにバインドされた処理にコピーされ、この場合、ユーザーコンテキストは、このユーザーコンテキストを共有メモリ領域にコピーし戻すことによりVMから分離されることができる。また、前述したように、幾つかの実施例において、ユーザーコンテキストを共有メモリ領域にコピーすることは、もし、前のバージョンのユーザーコンテキストが依然として共有メモリ領域に存在すれば、新たなバージョンのユーザーコンテキストの生成をもたらすことができる。VMをワーク処理にバインドすることと同様に、VMのバインドをワーク処理から解除することは、また、簡単で低コストのオペレーションである:共有メモリのVMのブロックは、単純に、ワーク処理のアドレス空間からマッピング解除されることができる。
ユーザーコンテキストがVMから分離され、VMのバインドがワーク処理から解除された後、VMとワーク処理は、両方とも、利用可能なものとしてマークされ、そして、他のリクエストを処理するためにサーバーによって使用されることができる。
処理1550におけるオペレーションは、別のシーケンス(例えば、利用可能な処理の選択は、利用可能なVMの選択と同時、または、その前後に発生することができる)において、サーバーの異なるコンポーネントによって実行されることができる。例えば、配信処理(例えば、図12の配信処理410)は、利用可能なワーク処理を選択し、単にユーザーリクエストを選択された処理に伝送して、それを利用可能なVMを選択するための処理に任せ、そのVMを処理にバインドし、ユーザーリクエストに対応するユーザーコンテキストを識別し、そしてユーザーコンテキストを選択されたVMに関連づけることができる。あるいは、配信処理は、幾つかのそれらのオペレーション自体を実行することができる−例えば、配信処理は、利用可能なVMを選択し、関連するユーザーコンテキストを識別し、そして、選択されたVMの識別と、識別されたユーザーコンテキストをワーク処理に送ることができる。他の代替が可能であり、それは、配信処理、ワーク処理、またはサーバーにおける追加的コンポーネントがオペレーションを実行する。
上述した技術は、ユーザーコンテキストとオブジェクトの共有を含み、他の環境においても使用されることができる。例えば、この技術は、VMが処理に取り付けられ、そして処理から取り外されるところのサーバー実施例において使用されることができる。図16は、このようなサーバーにおいてリクエストを処理するための処理1650の例を示すフローチャートである。処理1650において、ワーク処理のプールはサーバーに割り当てられ、そしてVMはワーク処理のそれぞれにおいて初期化される(1652)。各VMはVMの寿命期間の間にそのワーク処理にバインドされ、このことは、VMがワーク処理からとりはずされて他のワーク処理に取り付けられることができないことを意味する。
処理1550におけるのと同様に、ユーザーコンテキストは、各ユーザーセッションのために生成され、そしてサーバーにおける共有メモリ領域に格納される(1654)。サーバーがユーザーセッションからリクエストを受信すると(1656)、それは、対応するユーザーコンテキストを識別し(1658)、そしてワーク処理のプールから利用可能な処理を選択する(1660)。そして、ユーザーコンテキストは、(例えば、ユーザーコンテキストを選択された処理にバインドすることにより)選択された処理におけるVMと関連づけられる(1666)。そして、リクエストは、ユーザーコンテキストと共に、選択された処理におけるVMを実行することにより処理されることができる(1668)。ユーザーリクエストが処理されると、ユーザーコンテキストは、(例えば、ユーザーコンテキストを、選択された処理から共有メモリ領域にコピーし戻すことにより)VMから分離されることができる(1670)。そして、ワーク処理(およびその関連するVM)は、利用可能なものとしてマークされ、そして他のリクエストを処理するためにサーバーによって使用されることができる。
図15および図16の比較から理解されるように、処理1550と処理1650は、後者の処理がワーク処理からのVMのバインドとその解除を含まないことを除いて、同様である。処理1650は、より少ないオペレーションを含むにもかかわらず、その処理−すなわち、VMがワーク処理に取り付けられたり取り外されることのない処理−を実施するサーバーは、処理取り付け可能なVMを使用するサーバーと同様に効率的ではないようである。なぜなら、VMが前者のサーバーにおいてブロックしたときに、VMが稼動しているワーク処理は、他のリクエストを処理するために使用できないからである。これに対し、処理取り付け可能なVMを備えるサーバーにおいては、VMがブロックしたとき、そのVMは、そのワーク処理からデリートされることができ、そして他のVMがその場所に取り付けられて他のリクエストに取り組むために使用されることができる。
この明細書で述べられる本技術の種々の代替および最適化が可能である。例えば、資源消費および性能は、全てのVMに対して共通のデータを共有メモリに格納し、そしてこのようなデータを全てのワーク処理にマッピングすることにより、さらに改善されることができる。もし、タイプ情報(例えば、ロードされたJava(登録商標)クラスのランタイム表現)が、この方法で共有されれば、クラスローディングのためのオーバーヘッド、検証、および各VMのためのレゾリューション(resolution)が低減されることができる。
他の例として、代替メカニズムがデータと情報(VMとユーザーコンテキストの両方を含む)を共有するために使用されることができ−例えば、情報は、共有メモリよりはむしろ、ファイルまたはメッセージングシステムの使用を通じて共有されることができる。しかしながら、このようなメカニズムは、共有されるべき情報を存続させ、その存続を解除するためには、一層複雑で高価なオペレーションを必要とするかもしれないので、共有メモリほど望ましくはないかもしれない。
さらに他の例として、本明細書で述べた処理は、望ましい結果を達成するためには、示された特定のオーダー、またはシーケンシャルオーダーを必要としない。例えば、図15および16に示された処理において、ユーザーコンテキストを生成し、識別し、VMと関連づけるためのオペレーションは、処理全体の内の多くの異なる場所で実行されることができる。本明細書で述べられた処理の或る実施例では、マルチタスクおよび並列処理が好ましい。
さらに、種々のコンポーネントとエンティティ(entities)が、本明細書で述べた処理におけるオペレーションを実行するために使用されることができる。例えば、処理1550におけるオペレーションは、サーバー内の別のコンポーネントによって実行されることができる。例えば、一実施例において、配信処理(例えば、図12における配信処理410)は、利用可能なワーク処理を選択し、単に、選択された処理にユーザーリクエストを伝送して利用可能なVMを選択するための処理に任せ、そのVMを処理にバインドし、ユーザーリクエストに対応するユーザーコンテキストを識別し、そしてユーザーコンテキストを、選択されたVmに関連づける。あるいは、配信処理は、幾つかのそれらのオペレーション自体を実行することができる−例えば、配信処理は、利用可能なVMを選択し、関連するユーザーコンテキストを識別し、そしてワーク処理に識別されたユーザーコンテキストと選択されたVMの識別を送る。他の代替が可能であり、それは、配信処理、ワーク処理、またはサーバーにおける追加的または別のコンポーネントがオペレーションを実行する。例えば、サーバーは、配信処理を用いることなく実施されることができ、他のメカニズムが、ワーク処理間でリクエストを分配するために使用されることができる。
本発明と本明細書において述べられた機能的オペレーションの全ては、本明細書で開示された構造的手段、その構造的等価物、またはそれらの組み合わせを含み、デジタル電子回路、またはコンピュータソフトウェア、ファームウェア、またはハードウェアで実施されることができる。本発明は、1又は2以上ののコンピュータプログラムプロダクト、すなわち、例えば、プログラマブルプロセッサ、コンピュータ、または複数のコンピュータなどのデータ処理装置によって実行されるための、または上記データ処理装置のオペレーションを制御するための、例えば、マシン読み取り可能な記憶装置または伝搬信号において、明白に具現化される1又は2以上のコンピュータプログラムとして実施されることができる。コンピュータプログラム(プログラム、ソフトウェア、ソフトウェアアプリケーション、またはコードとして知られる)は、コンパイルまたはインタプリットされた言語を含んで、どのような形式のプログラム言語で記述されることもでき、そしてそれは、スタンドアローンプログラムまたはモジュール、コンポーネント、サブルーチン、またはコンピューティング環境における使用に適した他のユニットなどを含んで、どのような形式でも展開されることができる。コンピュータプログラムは、必ずしもファイルに対応しない。プログラムは、他のプログラムまたはデータを保持するファイルの一部に、問題になっているプログラム専用の単一のファイルに、または、複数のコーディネートされたファイル(例えば、1又は2以上のモジュール、サブプログラム、コードの一部を格納するファイル)に格納されることができる。コンピュータプログラムは、展開されて、通信ネットワークによって相互接続されて複数のサイトに分散された、または、一つのサイトでの複数のコンピュータ上または一つのコンピュータ上で実行されることができる。
本発明の方法ステップを含む処理とロジックフローは、入力を処理し出力を生成することにより本発明の機能を実行するための1又は2以上のコンピュータプログラムを実行する1又は2以上のプログラマブルプロセッサによって実施されることができる。また、処理およびロジックフローは、例えば、FPGA(field programmable gate array)またはASIC(application-specific integrated circuit)などの特定用途のロジック回路によって実行されることができ、そして、本発明の装置は、上記特定用途のロジック回路として実施されることができる。
コンピュータプログラムの実行に適したプロセッサは、一例として、汎用と特定用途の両方のプロセッサ、および1又は2以上の任意の種類の任意のデジタルコンピュータを含む。通常、プロセッサは、読み出し専用メモリまたはランダムアクセスメモリまたはその両方から命令およびデータを入力する。コンピュータの本質的要素は、命令を実行するためのプロセッサと、命令とデータを格納するための1又は2以上のメモリデバイスである。通常、コンピュータは、また、例えば、磁気的、磁気光ディスク、または光ディスクなど、データを格納するための1又は2以上の大容量記憶装置を備え、または、上記大容量記憶装置からのデータの受信または上記大容量記憶装置へのデータの送出、あるいはその両方のために動作可能に結合されている。コンピュータプログラム命令とデータを具現化するのに適した情報キャリアは、全ての形式の不揮発性メモリを含み、一例として、例えば、EPROM、EEPROM、およびフラッシュメモリデバイスなどの半導体メモリ;例えば、内臓ハードディスクまたはリムーバブルディスクなどの磁気ディスク;磁気光ディスク;およびCD−ROMおよびDVD−ROMディスクがある。プロセッサおよびメモリは、特定用途のロジック回路によって補完されることができ、または特定用途のロジック回路に組み込まれることができる。
本発明は、コンピューティングシステムにおいて実施されることができ、このコンピューティングシステムは、バックエンドコンポーネント(例えば、データサーバー)、ミドルウェアコンポーネント(例えば、アプリケーションサーバー)、またはフロントエンドコンポーネント(例えば、ユーザーが本発明の実施例と情報をやり取りすることができるグラフィカルユーザーインターフェイスまたはWebブラウザを備えたクライアントコンピュータ)、またはこのようなバックエンド、ミドルウェア、およびフロントエンドコンポーネントの任意の組み合わせを含む。本システムのコンポーネントは、例えば、通信ネットワークなど、デジタルデータ通信の任意の媒体または形式によって相互接続されることができる。通信ネットワークの例は、LAN(Local Area Network)およびWAN(Wide Area Network)、例えばインターネットを含む。
コンピューティングシステムはクライアントとサーバーを含むことができる。クライアントとサーバーは、通常、互いに離れており、代表的には、通信ネットワークを通じて情報のやり取りを行う。クライアントとサーバーとの関係は、各自のコンピュータ上で稼動して互いにクライアント−サーバー関係を有するコンピュータプログラムのおかげで発生する。
本発明は、特定の実施例の観点で説明されたが、他の実施例が本願特許請求の範囲内で可能である。例えば、上述したように、本発明のオペレーションは、別のオーダーで実施されることができ、それでも望ましい結果を達成することができる。他の実施例は、本願特許請求の範囲内である。