(57)【要約】  本発明は、アプリケーションプログラム（５０）を複数のコンピュータ（Ｍ１、．．．Ｍｎ）上で同時に実行できるようにする修正されたコンピュータアーキテクチャ（５０、７１、７２）を開示する。各コンピュータにある共有メモリは、全てのメモリ読み取り要求がローカルで満たされるように修正及び／又は上書きによって更新される。初期プログラムロード（７５）又は類似のプログラムロード中、メモリが再度書き込まれ又は操作されることになる命令が識別される（９２）。全てのコンピュータにおける等価のメモリロケーションが更新されるようにする追加命令が挿入される（１０３）。特に、ＪＡＶＡ言語のクラス及びオブジェクトの初期化が開示され（１６２、１６３）、全てのコンピュータの全メモリロケーションが同じ方法で初期化される。【選択図】図８
2007534063.tif 000002
【特許請求の範囲】
【請求項１】
単一のコンピュータでのみ動作するように各々記述されているが、通信ネットワークによって相互接続された複数のコンピュータ上で同時に実行される少なくとも１つのアプリケーションプログラムを有する多重コンピュータシステムであって、
前記アプリケーションプログラムの異なる部分が前記コンピュータのうちの異なるコンピュータ上でほぼ同時に実行され、前記各部分において、実質的に同一な複数のオブジェクトが前記対応するコンピュータに各々作成され、各々は実質的に同一の名前を有し、前記同一の名前が付けられたオブジェクトの各々の初期コンテンツは実質的に同じであることを特徴とする多重コンピュータシステム。
【請求項２】
前記各コンピュータが分散ランタイム手段を含み、前記各コンピュータの分散ランタイム手段が全ての他のコンピュータと通信可能であり、これによって前記コンピュータの１つの上で実行する前記アプリケーションプログラムの一部が当該コンピュータにおいてオブジェクトを作成する場合には、前記作成されたオブジェクトが前記１つのコンピュータの分散ランタイム手段によって前記他のコンピュータ全てに伝播されることを特徴とする請求項１に記載のシステム。
【請求項３】
初期化ルーチンを挿入して前記アプリケーションプログラムがオブジェクトを作成する各インスタンスを修正することによって、前記各アプリケーションプログラムがロード前、ロード中、又はロード後に修正され、前記初期化ルーチンは、１つのコンピュータによって新規に作成されたあらゆるオブジェクトを前記他のコンピュータ全てに伝播することを特徴とする請求項２に記載のシステム。
【請求項４】
前記挿入された初期化ルーチンは、既存の初期化ルーチンを修正して、前記既存の初期化ルーチンが前記複数のオブジェクトの第１のオブジェクトの作成時に実行することができ、前記複数のオブジェクトの全ての次のオブジェクトの作成時に前記既存の初期化ルーチンを無効にすることを特徴とする請求項３に記載のシステム。
【請求項５】
前記アプリケーションプログラムは、ロード時の再コンパイル、ロード前の事前コンパイル、ロード前のコンパイル、実行時コンパイル、及びロード後で且つアプリケーションプログラムの関連部分の実行前の再コンパイルからなる手順のグループから選択される手順に従って修正されることを特徴とする請求項４に記載のシステム。
【請求項６】
前記修正アプリケーションプログラムは、マスタ／スレーブ転送、ブランチ転送、及びカスケード転送からなるグループから選択された手順に従って前記コンピュータの全てに転送されることを特徴とする請求項２に記載のシステム。
【請求項７】
通信リンクを介して相互接続され、単一のコンピュータでのみ動作するように各々記述された少なくとも１つのアプリケーションプログラムを同時に動作する複数のコンピュータであって、前記各コンピュータは、前記アプリケーションプログラムの異なる部分をほぼ同時に実行し、そのアプリケーションプログラム部分を実行中の前記各コンピュータは、前記各コンピュータに物理的に位置付けられたローカルメモリ内にだけオブジェクトを作成し、前記各コンピュータによって利用される前記ローカルメモリのコンテンツは、基本的に類似しているが、各瞬間では同一でなく、前記コンピュータの全てのコンピュータが、前記１つのコンピュータによって作成されたオブジェクトを他の前記コンピュータ全てに分散するための分散更新手段を有することを特徴とする複数のコンピュータ。
【請求項８】
前記又は前記各アプリケーションプログラムに割り当てられたローカルメモリ容量が実質的に同一であり、前記又は前記各アプリケーションプログラムが利用可能な総メモリ容量が、前記割り当てられたメモリ容量であることを特徴とする請求項７に記載の複数のコンピュータ。
【請求項９】
前記分散更新手段の全ては、前記ローカルメモリ読み取り速度よりも遅いデータ転送速度で前記通信リンクを介して伝達することを特徴とする請求項７に記載の複数のコンピュータ。
【請求項１０】
前記コンピュータの少なくとも幾つかは、種々の製造業者によって製造され、及び／又は種々のオペレーティングシステムを有することを特徴とする請求項７に記載の複数のコンピュータ。
【請求項１１】
単一のコンピュータでのみ動作するように各々記述された少なくとも１つのアプリケーションプログラムを同時に動作する方法であって、前記コンピュータが通信ネットワークによって相互接続されており、前記方法が、
（ｉ）前記コンピュータのうちの異なるコンピュータ上で前記アプリケーションプログラムの異なる部分を実行し、前記各部分に対して、前記対応するコンピュータにおいて実質的に同一な複数のオブジェクトを各々作成し、該オブジェクトの各々に実質的に同一の名前を持たせる段階と、
（ｉｉ）前記同一の名前が付けられたオブジェクトの各々の初期コンテンツを実質的に同じであるように作成する段階と、
を含む方法。
【請求項１２】
（ｉｉｉ）前記コンピュータの１つの上で実行される前記アプリケーションプログラムの一部が当該コンピュータにおいてオブジェクトを作成する場合には、前記作成されたオブジェクトを前記通信ネットワークを介して前記他のコンピュータの全てに伝播する段階を更に含む請求項１１に記載の方法。
【請求項１３】
（ｉｖ）１つのコンピュータによって作成されたあらゆるオブジェクトを前記他のコンピュータ全てに伝播する初期化ルーチンを挿入して前記アプリケーションプログラムによりオブジェクトが作成される各インスタンスを修正することによって、前記アプリケーションプログラムをロード前、ロード中、又はロード後に修正する段階を更に含む請求項１２に記載の方法。
【請求項１４】
（ｖ）ロード時の再コンパイル、ロード前の事前コンパイル、ロード前のコンパイル、実行時コンパイル、及びロード後で且つアプリケーションプログラムの関連部分の実行前の再コンパイルからなる手順のグループから選択される手順を利用して前記アプリケーションプログラムを修正する段階を更に含む請求項１３に記載の方法。
【請求項１５】
（ｖｉ）マスタ／スレーブ転送、ブランチ転送、及びカスケード転送からなるグループから選択される手順を利用して前記コンピュータの全てに前記修正アプリケーションプログラムを転送する段階を更に含む請求項１３に記載の方法。
【請求項１６】
単一のコンピュータでのみ動作するように記述されたアプリケーションプログラムをコンパイル又は修正して、前記アプリケーションプログラムの異なる部分を通信リンクを介して相互接続された複数のコンピュータのうちの異なるコンピュータ上でほぼ同時に実行させるようにする方法であって、
（ｉ）前記コンピュータの１つを利用してオブジェクトを作成する命令を検出する段階と、
（ｉｉ）前記各検出されたオブジェクト作成命令に従って初期化ルーチンを起動する段階と、
を含み、
前記初期化ルーチンは、各作成されたオブジェクトを前記コンピュータの残りに転送することを特徴とする方法。
【請求項１７】
前記各コンピュータへの前記アプリケーションプログラムのロード前、ロード中、或いはロード後で且つ前記アプリケーションプログラムの関連部分の実行前に行われる請求項１６に記載の方法。
【請求項１８】
単一のコンピュータでのみ動作するよう記述された単一のアプリケーションプログラムの個々のスレッドが、通信リンクを介して相互接続された複数のコンピュータのうちの異なる対応するコンピュータ上で各々が同時に処理されるマルチスレッド処理コンピュータオペレーションにおいて、
各スレッドを処理する前記コンピュータに物理的に関連付けられたローカルメモリ内で作成されたオブジェクトを前記通信リンクを介して他の前記各コンピュータのローカルメモリに伝達する段階を含む改良方法。
【請求項１９】
１つの前記スレッドに関連付けられる前記メモリ内に作成されたオブジェクトが、前記１つのスレッドの前記コンピュータによって他の前記コンピュータ全てに伝達されることを特徴とする請求項１８に記載の改良方法。
【請求項２０】
１つの前記スレッドに関連付けられる前記メモリ内に作成されたオブジェクトが、別の前記スレッドに関連付けられたコンピュータに送信されることにより、前記他のコンピュータ全てに送信されることを特徴とする請求項１８に記載の改良方法。
【請求項２１】
単一のコンピュータでのみ動作するよう記述されたアプリケーションプログラの矛盾のない初期化を保証する方法であって、前記アプリケーションプログラムの異なる部分が、通信ネットワークを介して相互接続された複数のコンピュータの異なるコンピュータ上で各々同時に実行されることになり、前記方法が、
（ｉ）前記アプリケーションプログラムをロード時、又はロード前、或いはロード後に精査して初期化ルーチンを定義する各プログラム段階を検出する段階と、
（ｉｉ）前記初期化ルーチンを修正して前記コンピュータの全ての矛盾のないオペレーションを保証する段階と、
を含む方法。
【請求項２２】
前記初期化ルーチンは、前記コンピュータのいずれか１つによる第１オブジェクトの作成時にのみ一度実行されるように修正され、前記コンピュータの残りによる前記オブジェクトの各々の次のピアコピーの作成時に無効になるよう修正されることを特徴とする請求項２１に記載の方法。
【請求項２３】
前記段階（ｉｉ）が、
（ｉｉｉ）前記コンピュータの１つで前記初期化ルーチンをロードし実行する段階と、
（ｉｖ）前記１つのコンピュータによって前記初期化ルーチンを修正する段階と、
（ｖ）前記修正された初期化ルーチンを前記残りのコンピュータの各々に転送する段階と、
を含む請求項２１又は２２に記載の方法。
【請求項２４】
前記修正された初期化ルーチンが、前記１つのコンピュータによって前記残りのコンピュータの各々に直接提供される請求項２３に記載の方法。
【請求項２５】
前記修正された初期化ルーチンは、前記１つのコンピュータから前記残りのコンピュータの各々に順次にカスケード方式で提供される請求項２３に記載の方法。
【請求項２６】
前記段階（ｉｉ）が、
（ｖｉ）前記コンピュータの１つに前記初期化ルーチンをロードし修正する段階と、
（ｖｉｉ）前記１つのコンピュータが前記残りのコンピュータの各々に前記未修正の初期化ルーチンを送信する段階と、
（ｖｉｉｉ）前記残りのコンピュータの各々が前記初期化ルーチンを受信した後に前記初期化ルーチンを修正する段階と、
を含む請求項２１又は２２に記載の方法。
【請求項２７】
前記未修正の初期化ルーチンは、前記１つのコンピュータによって前記残りのコンピュータの各々に直接提供される請求項２６に記載の方法。
【請求項２８】
前記未修正の初期化ルーチンは、前記１つのコンピュータから前記残りのコンピュータの各々に順次にカスケード方式で提供される請求項２６に記載の方法。
【請求項２９】
記憶媒体内に記憶され、請求項１１又は１６又は１８又は２１に記載の方法の実行を複数のコンピュータに許可するように動作可能なプログラム命令のセットを含むコンピュータプログラム製品。
【請求項３０】
通信ネットワークを介して相互接続された複数のコンピュータにおいて、単一のコンピュータでのみ動作するよう記述されているが、前記複数のコンピュータが同時に実行されるアプリケーションプログラムの矛盾のない初期化を保証するよう動作可能な複数のコンピュータであって、前記コンピュータは、請求項１１又は１６又は１８又は２１に記載の方法を実行するようプログラムされているか、或いは請求項２９に記載のコンピュータプログラム製品がロードされていることを特徴とする複数のコンピュータ。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、コンピュータに関し、詳細には、通信ネットワークを介して相互接続された複数のコンピュータ上で同時にアプリケーションプログラムを動作することができる改良型マシーンアーキテクチャに関する。
【背景技術】
【０００２】
コンピュータ及びコンピュータ関係の利用が出現して以来、コンピュータのソフトウェアは、単一のマシーン上で実行するように記述されてきた。図１に示されるように、当該従来技術の単一マシーン１は、バス４を介してメモリ３に接続された中央処理ユニット又はＣＰＵ２から構成される。また、モニタ５、キーボード６、及びマウス７のような単一マシーン１の種々の他の機能ユニットもバス４に接続されている。
【０００３】
マシーン１の性能に対する基本的制限は、ＣＰＵ２によって操作されるデータ及びこれらの操作の結果をバス４によって移動する必要があることである。バス４は、バスへのアクセスを要望するユニットによって形成されるいわゆるバス「待ち行列」、コンテンション問題、及び同様のものを含む幾つかの問題の影響を受ける。これらの問題は、キャッシュメモリを含む種々の方策によってある程度までは軽減することができるが、このような方策は、マシーン１の管理オーバーヘッドを必然的に増大させる。
【０００４】
当然、何年もの間マシーン性能を向上させる種々の試みがなされてきた。１つの手法は、対称的マルチプロセッサを使用することである。この従来技術の手法は、いわゆる「スーパー」コンピュータで使用されており、図２に概略的に示されている。ここで複数のＣＰＵ１２は、グローバルメモリ１３に接続されている。同様に、ボトルネックは、ＣＰＵ１２とメモリ１３との間の通信で発生する。このプロセスは、「シングルシステムイメージ」と呼ばれている。１つだけのアプリケーションと、グローバルメモリにわたり分散されるアプリケーション用のメモリの１つの全体コピーが存在する。単一のアプリケーションは、完全にトランスペアレントにいずれかのメモリロケーションとの間で読み込み及び書き込み（すなわち共有）を行うことができる。
【０００５】
ネットワークを介して相互接続された幾つかのこのようなマシーンが存在する場合には、これは、単一のマシーン用に記述された単一のアプリケーションを採用し、必要とされるメモリ資源を小部分に分割することによって達成される。次いで、これらの小部分は、幾つかのコンピュータにわたって分散され、全てのＣＰＵ１２がアクセス可能なグローバルメモリ１３を形成する。この手順は、単一の実行中のアプリケーションプログラムからメモリパーティションをマスキング又は隠すことに依存する。１つのマシーンの１つのＣＰＵが、異なるマシーン内に物理的に位置付けられたメモリロケーションにアクセス（ネットワークを介して）する必要がある場合には、性能が低下する。
【０００６】
スーパーコンピュータは、高速の計算速度を達成する点においては技術的に成功しているが、これらが本質的に複雑であることによって、製造だけでなく管理に対しても極めて高価なものである点で商業的には成功していない。特に、シングルシステムイメージの概念は、「製品」である（すなわち大量生産された）コンピュータ及びネットワークを越えて拡張することは決してできない。特に、シングルシステムイメージの概念は、超高速（及び従って極めて高価）ネットワークによって相互接続された超高速（及び同様に極めて高価）コンピュータ上でのみ実用的なアプリケーションが見られた。
【０００７】
複数のマシーンを使用することで増大されたコンピュータパワーの別の可能性は、図３に概略的に示されている分散コンピューティングの従来技術の概念から生じる。この公知の構成では、単一のアプリケーションプログラム（Ａｐ）は、その作成者（又はアプリケーションプログラムについてよく理解している別のプログラマー）によって種々の離散的タスクに区分され、例えば図３のケースｎが整数３である３つのマシーン上で実行できるようにする。ここでの目的は、マシーンＭ１．．．Ｍ３の各々がアプリケーション全体のうちで異なる１／３を実行することであり、更に、種々のマシーンに加えられる負荷をほぼ等しくすることである。マシーンは、通信リンク、インターネット、イントラネット、ローカルエリアネットワーク、及び同様のものなどの種々の形式で提供することができるネットワーク１４を介して通信する。通常、このようなネットワーク１４のオペレーションの速度は、個々のマシーンＭ１、Ｍ２、その他の各々におけるバス４のオペレーション速度よりもかなり遅い。
【０００８】
分散コンピューティングには幾つかの欠点がある。第１に、アプリケーションを分割するジョブは困難であり、これはマニュアルで行わなければならない。第２に、ネットワーク１４を介したデータ、部分的な結果、結果、及び同様のものの通信は、管理上のオーバーヘッドである。第３に、分割が必要であることにより、例えば３つに分割されたアプリケーションが４つのマシーン上ではうまく動作しないので、より多くのマシーンを用いることによって機能を高めることが極めて困難になる。第４に、マシーンの１つを無効にする必要がある場合、システム全体の性能がかなり低下する。
【０００９】
別の従来技術の構成は、図４に概略的に示された「クラスタ」を介したネットワークコンピューティングとして公知である。この方法では、アプリケーション全体が機械Ｍ１、Ｍ２．．．Ｍｎの各々にロードされる。各機械は、共通のデータベースと通信するが、他の機械とは直接通信しない。各機械は同じアプリケーションを実行するが、異なる「ジョブ」を実行しており、固有のメモリだけを使用する。これは、その各々が列車のチケットを一般の人に販売する幾つかの窓口に幾分類似している。この方法は機能を実行し、拡張可能であるが、大抵はネットワークを管理するのが難しいといった欠点がある。
【００１０】
ＪＡＶＡ及びＭＩＣＴＰＳＯＦＴ．ＮＥＴなどのコンピュータ言語には、プログラマーが扱う構成体の２つの主要なタイプがある。ＪＡＶＡ言語では、これらはオブジェクト及びクラスとして知られる。オブジェクトが作成される度に、「＜ｉｎｉｔ＞」として知られる初期化ルーチンが存在する。同様に、クラスがロードされる度に、「＜ｃｌｉｎｉｔ＞」として知られる初期化ルーチンが存在する。他の言語は異なる項を使用するが、類似の概念を利用する。
【発明の開示】
【００１１】
本発明は、アプリケーションプログラムが複数のコンピュータ上で同時に動作するコンピューティング環境を開示する。このような環境では、上述の初期化ルーチンが機械の全てにわたって矛盾のない方式で確実に動作することが必要である。これが本発明の起源である矛盾のない初期化の目標である。
【００１２】
本発明の第１の態様によれば、単一のコンピュータでのみ動作するように各々が記述されているが、通信ネットワークによって相互接続された複数のコンピュータ上で同時に実行する少なくとも１つのアプリケーションプログラムを有する多重コンピュータシステムが開示され、アプリケーションプログラムの異なる部分がコンピュータのうちの異なるコンピュータ上でほぼ同時に実行され、各部分において同様の複数の実質的に同一のオブジェクトが対応するコンピュータに各々作成され、各々は実質的に同一の名前を有し、同一の名前が付けられたオブジェクトの各々の初期コンテンツは実質的に同じである。
【００１３】
本発明の第２の態様によれば、通信リンクを介して相互接続され、単一のコンピュータでのみ動作するように各々記述された少なくとも１つのアプリケーションプログラムを同時に動作する複数のコンピュータが開示され、各コンピュータは、アプリケーションプログラムの異なる部分をほぼ同時に実行し、そのアプリケーションプログラム部分を実行中の各コンピュータは、各コンピュータに物理的に位置付けられたローカルメモリ内にだけオブジェクトを作成し、各コンピュータによって利用されるローカルメモリのコンテンツは、基本的に類似しているが、各瞬間では同一ではなく、コンピュータのうちの全てのコンピュータが、１つのコンピュータによって作成されたオブジェクトを他の前記コンピュータ全てに分散するための分散更新手段を有する。
【００１４】
本発明の第３の態様によれば、単一のコンピュータでのみ動作するように各々記述された少なくとも１つのアプリケーションプログラムを複数のコンピュータ上で同時に実行する方法が開示され、コンピュータが、通信ネットワークによって相互接続され、本方法が、（ｉ）コンピュータのうちの異なるコンピュータ上でアプリケーションプログラムの異なる部分を実行し、各部分に対して、対応するコンピュータにおいて同様の複数の実質的に同一のオブジェクトを各々作成し、該オブジェクトの各々に実質的に同じ名前を持たせる段階と、（ｉｉ）同一の名前が付けられたオブジェクトの各々の初期コンテンツを実質的に同じであるように作成する段階と、を含む。
【００１５】
本発明の第４の態様によれば、単一のコンピュータでのみ動作するように記述されたアプリケーションプログラムをコンパイル又は修正して、通信リンクを介して相互接続された複数のコンピュータのうちの異なるコンピュータ上でほぼ同時に実行できるようにする方法が開示され、本方法は、（ｉ）コンピュータの１つを利用してオブジェクトを作成する命令を検出する段階と、（ｉｉ）各検出されたオブジェクト作成命令に従って初期化ルーチンを起動する段階とを含み、初期化ルーチンはコンピュータの残りに各作成されたオブジェクトを転送することを特徴とする方法。
【００１６】
本発明の第５の態様によれば、単一のコンピュータでのみ動作するよう記述された単一アプリケーションプログラムの個々のスレッドが、通信リンクを介して相互接続された複数のコンピュータのうちの異なる対応するコンピュータ上で各々が同時に処理されるマルチスレッド処理コンピュータオペレーションが開示され、改良点として、各スレッドを処理するコンピュータに物理的に関連付けられたローカルメモリ内で作成されたオブジェクトを通信リンクを介して他の各コンピュータのローカルメモリに伝達する段階を含む。
【００１７】
本発明の第６の態様によれば、単一のコンピュータでのみ動作するよう記述されたアプリケーションプログラムであるが、その異なる部分が通信ネットワークを介して相互接続された複数のコンピュータの異なるコンピュータ上で各々同時に実行されるアプリケーションプログラムの矛盾のない初期化を保証する方法が開示され、本方法は、（ｉ）前記アプリケーションプログラムをロード時、又はロード前、又はロード後に精査して、初期化ルーチンを定義する各プログラム段階を検出する段階と、（ｉｉ）前記初期化ルーチンを修正して全てのコンピュータの矛盾のないオペレーションを保証する段階と、を含む。
【００１８】
本発明の第７の態様によれば、単一のコンピュータでのみ動作するように作成されたコンピュータプログラムが開示されるが、製品は、記憶媒体内に記憶され、上述の方法を複数のコンピュータが実行するのを許可するように動作可能なプログラム命令のセットを含む。
【発明を実施するための最良の形態】
【００１９】
本発明の実施形態を図面を参照しながら説明する。
【００２０】
本明細書は、説明された実施形態の種々の態様を実装する実際のプログラムフラグメントを提供する添付書Ａ及びＢを含む。添付書Ａはフィールドに関し、添付書Ｂは初期化に関する。
【００２１】
図５に関連して、本発明の好ましい実施形態によれば、単一のアプリケーションプログラム５０は、ネットワーク５３を介して通信する幾つかのマシーンＭ１、Ｍ２．．．Ｍｎ上で同時に動作することができる。以下に明らかになるように、マシーンＭ１、Ｍ２．．．Ｍｎの各々は、各マシーンＭ１、Ｍ２．．．Ｍｎ上で同じアプリケーションプログラム５０で動作し、従って、マシーンＭ１、Ｍ２．．．Ｍｎの全ては、同じアプリケーションコード及びデータ５０を有する。同様に、マシーンＭ１、Ｍ２．．．Ｍｎの各々は、各マシーンＭ１、Ｍ２．．．Ｍｎ上の同じ（又は実質的に同じ）モディファイア(modifier,変更子)５１で動作し、従って、マシーンＭ１、Ｍ２．．．Ｍｎの全ては、５１／２で示されるマシーンＭ２のモディファイアーと同じ（又は実質的に同じ）モディファイアー５１を有する。更に、各マシーンＭ１、Ｍ２．．．Ｍｎ上でのアプリケーション５０のロード中、又は実行前に、各アプリケーション５０は、同じ規則（又は僅かな最適化変更が各モディファイアー５１／１．．．５１／ｎで許可されているので、実質的に同じ規則）に従って対応するモディファイアー５１で修正されている。
【００２２】
上述の構成の結果として、マシーンＭ１、Ｍ２．．．Ｍｎの各々が、例えば１０ＭＢの共有メモリ容量を有する場合には、各アプリケーション５０が利用可能な合計共有メモリは、予想されるように１０ｎＭＢではなくむしろ１０ＭＢだけである。しかしながら、これによって改良されたオペレーションがどのように生じるかは、以下で明らかになるであろう。当然、各マシーンＭ１、Ｍ２．．．Ｍｎは、非共有メモリ容量を有する。マシーンＭ１、Ｍ２．．．Ｍｎの非共有メモリ容量は、通常ほぼ等しいが、必須ではない。
【００２３】
図６に概略的に示されるように仮想マシーンを作成することによって、アプリケーションの特定の言語でマシーン（種々の製造業者の１つによって生産され、種々の異なる言語の１つで動作するオペレーティングシステムを有する）を動作させることは従来技術から公知である。図６の従来技術の構成は、Ｊａｖａ言語で記述されＪａｖａ仮想マシーン６１内で実行するアプリケーション５０の形式を取る。従って、アプリケーションの目的とする言語がＪＡＶＡ言語である場合、マシーン製造業者及びマシーンの内部の詳細に関わらず、ＪＡＶＡコードを操作できるＪＡＶＡ仮想マシーンが作成される。更なる詳細については、米国のＳｕｎ  Ｍｉｃｒｏｓｙｓｔｅｍｓ  Ｉｎｃ．のＴ．Ｌｉｎｄｈｏｌｍ及びＦ．Ｙｅｌｌｉｎによる「Ｔｈｅ  ＪＡＶＡ  Ｖｉｒｔｕａｌ  Ｍａｃｈｉｎｅ  Ｓｐｅｃｉｆｉｃａｔｉｏｎ”  ２ｎｄ  Ｅｄｉｔｉｏｎ（ＪＡＶＡ仮想マシーン仕様）」第２版を参照されたい。
【００２４】
図６のこの公知の従来技術の構成は、図７に見られるように「分散ランタイム」又はＤＲＴ７１と便宜上呼ばれる付加的な機能を提供することによって、本発明の好ましい実施形態に従って修正される。図７では、アプリケーション５０は、矢印７５によって示されるロード手順で分散ランタイムシステム７１を介してＪａｖａ仮想マシーン７２にロードされる。分散ランタイムシステムは、分散コンピューティング環境（ＤＣＥ）の名称でＯｐｅｎ  Ｓｏｆｔｗａｒｅ  Ｆｏｕｎｄａｔｉｏｎから利用可能である。特に、分散ランタイム７１は、最初にＪＡＶＡ仮想マシーン７２を作成するように、ＪＡＶＡアプリケーション５０の矢印７５によって示されるロード手順中に作動し始める。ロード中のオペレーションのシーケンスは、図９に関して以下に説明する。
【００２５】
図８は、各々が図７に示されるようにＪＡＶＡ仮想マシーンを用いる図５の構成の修正された形式を示す。同様に同じアプリケーション５０が各マシーンＭ１、Ｍ２．．．Ｍｎにロードされることは明らかであろう。しかしながら、矢印８３によって示されているがマシーンハードウェアからは物理的に経路指定されている各マシーンＭ１、Ｍ２．．．Ｍｎ間の通信は、各マシーン内の個々のＤＲＴ７１／１．．．７１／ｎによって制御される。従って、実際にはこれは、マシーンＭ１、Ｍ２．．．Ｍｎ自体ではなくネットワーク７３を介して互いに通信しているＤＲＴ７１／１．．．７１／ｎとして概念化することができる。
【００２６】
ここで図７及び９を参照すると、ローディング手順７５の間、各ＪＡＶＡ仮想マシーン７２を作成するためにロードされているプログラム５０が修正される。この修正は図９の９０で開始し、ロードされているアプリケーション５０において全メモリロケーション（ＪＡＶＡではフィールドと呼ばれるが、他の言語でも同等の用語が使用される）を検出する初期ステップ９１を包含する。このようなメモリロケーションは、ステップ９２及び９３での連続した処理において識別される必要がある。ローディング手順７５中のＤＲＴ７１は、メモリロケーション全てのリストを作成し、このようにしてオブジェクト及びクラスによってリストされるＪＡＶＡフィールドを識別する。揮発性フィールド及び同期フィールドの両方がリストされる。
【００２７】
修正手順の次のステップ（図９の９２で示される）は、全処理動作を特定するために実行可能なアプリケーションコードをサーチすることであり、該全処理動作では、ステップ９１で作成されたリストに対応するフィールド値を操作又は変更し、これによって対応するメモリロケーションでの値が変更されるようにフィールドに書き込む。フィールド値を変更するこのようなオペレーション（通常、ＪＡＶＡ言語におけるｐｕｔｓｔａｔｉｃ又はｐｕｔｆｉｅｌｄ）が検出された場合、フィールドの値が変わったことを全ての他のマシーンに確実に通知されるように、ステップ９３で「更新伝播ルーチン(updating propagating routine)」がプログラムのこの場所に挿入される。その後、ロード手順は、図９のステップ９４によって示される通常の方法で続行される。
【００２８】
ロード中の初期修正の他の形式が図１０に示されている。ここで開始及びリスティングステップ９０及び９１並びにサーチステップ９２は、図９と同じである。しかしながら、処理スレッドが更新を実行するステップ９３で「更新伝播ルーチン」を挿入するのではなく、「警報ルーチン(alert routine)」がステップ１０３で挿入される。「警報ルーチン」は、処理に使用されずＤＲＴに割り当てられる１つ又は複数のスレッドに対し必要な伝播を実行するよう指示を与える。このステップ１０３は、より低いオーバーヘッドを生じる簡単な代替手段である。
【００２９】
ロード手順中にこの初期修正が行われると、次いで、図１１及び１２に示されるマルチスレッド処理オペレーションのいずれか１つが行われる。図１１で分かるように、スレッド１１１／１．．．１１１／４からなるマシーン上のマルチスレッド処理１１０が行われ、第２スレッド１１１／２の処理（この実施例での）では、スレッド１１１／２がフィールド値の変更をステップ１１３で認識することになる。このステップで、スレッド１１１／２の通常の処理はステップ１１４で停止し、同じスレッド１１１／２は、ステップ１１３で行われた変更フィールドのアイデンティティ及び変更値をネットワーク５３を介して全ての他のマシーンＭ２．．．Ｍｎに通知する。次いでステップ１１５で、当該通信手順の最後において、スレッド１１１／２は、フィールド値の変更がある次のインスタンスまで処理を再開する。
【００３０】
図１２に示された他の構成では、ステップ１１３でスレッド１２１／２がフィールド値の変更を認識すると、スレッド１２１／２は、ＤＲＴ処理１２０に割り当てられた別のスレッド１２１／１がステップ１２８によりネットワーク５３を介しステップ１１３で検出された変更フィールドのアイデンティティ及び変更値を全ての他のマシーンＭ２．．．Ｍｎに伝播するようにＤＲＴ処理１２０（ステップ１２５及び矢印１２７によって示されるように）に指示する。これは、迅速に実行できるオペレーションであり、すなわち、スレッド１１１／２がステップ１１５で処理を再開する前に、該初期スレッド１１１／２の処理は、ステップ１２５で示されるように瞬間的に中断される。次いで、変更（矢印１２７によって示されるような）を通知された他のスレッド１２１／１は、その変更をステップ１２８で示されるようにネットワーク５３を介して他のマシーンＭ２．．．Ｍｎの各々に伝達する。
【００３１】
図１２のこの第２の構成は、種々のスレッド１１１／１．．．１１１／３及び１２１／１（これらは一般に均等要求の影響を受けない）の処理能力をうまく利用し、増大する「ｎ」のサイズと共に良好な拡張を与える（ｎは２以上の整数であって、ネットワーク５３に接続されアプリケーションプログラム５０を同時に実行するマシーンの総数を表す）。どの構成が使用されるかに関わらず、ステップ１１３で検出された変更フィールド及びアイデンティティ及び値は、ネットワーク上の他のマシーンＭ２．．．Ｍｎ全てに伝播される。
【００３２】
これは図１３に示され、ＤＲＴ７１／１及び図１２のスレッド１２１／１（図１３のステップ１２８によって表わされる）は、マシーンＭ１での処理によってネットワーク５３を介して図１２のステップ１１３で作成されたリストされたメモリロケーションのアイデンティティ及び変更値を他のマシーンＭ２．．．Ｍｎの各々に送信する。
【００３３】
他のマシーンＭ２．．．Ｍｎの各々は、ネットワーク５３からアイデンティティと値のペアを受信し且つ新しい値をローカルの対応するメモリロケーションに書き込むことにより、マシーンＭｎのための図１３のステップ１３５及び１３６によって示された動作を実行する。
【００３４】
分散型ソフトウェアを利用する図３の従来技術の構成では、１つのマシーンのソフトウェアから別のマシーンに物理的に位置付けられたメモリへのメモリアクセスは、マシーンを相互接続するネットワークによって許可される。しかしながら、このようなメモリアクセスは、マシーンの中央処理ユニットの１０6−１０7サイクルのオーダーの処理に遅延を生じる可能性がある。これは大部分が、複数の相互接続されたマシーンの性能の低下に起因する。
【００３５】
しかしながら、図８に関して上述された本構成では、全フィールドの現在の値は、メモリの読み取り要求を生成する処理を実行しているマシーン上に記憶されるので、データの全読み取りがローカルで達成されることを理解されたい。このようなローカル処理は、中央処理ユニットの１０2−１０3サイクル内で達成することができる。従って、実際には読み取りを伴うメモリアクセスを実質的には待機することはない。
【００３６】
しかしながら、ほとんどのアプリケーションソフトウェアは、メモリを頻繁に読み取るが、書き込みは比較的まれにしか行わない。この結果、メモリの書き込み又は再書き込みの速度は、メモリの読み取り速度に比べて比較的遅い。メモリの書き込み又は再書き込みに対するこの低速の要求に起因して、フィールドは、低価格製品ネットワーク５３を介した比較的低速で頻繁に更新することができ、更にこの低速では、メモリへ書き込むためのアプリケーションプログラムの要求を満たすのに十分である。この結果、図８の構成の性能は、図３の構成よりも極めて優れていることになる。
【００３７】
上記に関連した別の修正形態において、変更フィールドのアイデンティティ及び値をバッチにグループ分けし、種々のマシーンを相互接続するネットワーク５３の通信速度に対する要求を更に低減することができる。
【００３８】
フィールドを最初に記録する際に各ＤＲＴ７１によって作成されたテーブルでは、各フィールドに対してネットワーク全体で共通であり且つネットワークが認識する名前又はアイデンティティが存在することは当業者には明らかであろう。しかしながら、個々のマシーンでは、各マシーンが固有の内部プロセスに従って異なるロケーションで変更フィールド値を漸次記憶するので、所与の名前付きフィールドに対応するメモリロケーションは時間と共に変わることになる。従って、ＤＲＴの各々におけるテーブルは、一般には異なるメモリロケーションを有するが、各グローバル「フィールド名」は、異なるメモリロケーション内に記憶された同じ「フィールド値」を有することになる。
【００３９】
ロード中のアプリケーションプログラムの上述の修正は、以下の最大５つの方法で達成可能であることが当業者には明らかであろう。
（ｉ）ロード時の再コンパイル
（ｉｉ）プリコンパイルによるロード前の処理
（ｉｉｉ）ロード前のコンパイル
（ｉｖ）「実行時」（ＪＩＴ）コンパイル、
（ｖ）ロード後の再コンパイル（しかしながら、又は例えば、分散環境での関連した又は対応するアプリケーションコードを実行する前）
【００４０】
従来、用語「コンパイル」とは、例えばソースからオブジェクトコード、又は１つの言語から別の言語へのコード又は言語における変更を意味する。明確には、本明細書において用語「コンパイル」（及びその文法的に等価なもの）の使用は同じコード又は言語内に限定されず、修正形態を含む又は包含することができる。
【００４１】
第１の実施形態において、特定のマシーン、例えばマシーンＭ２は、それ自体にアプリケーションコードをロードし、これを修正し、次いで他のマシーンＭ１、Ｍ３．．．Ｍｎの各々に（順次又は同時に）修正コードをロードする。「マスタ／スレーブ」と呼ぶ場合があるこの構成では、マシーンＭ１、Ｍ３、．．．Ｍｎの各々が、マシーンＭ２によって与えられるものをロードする。
【００４２】
更に別の実施形態において、各マシーンはアプリケーションコードを受け取るが、これを修正し、修正コードをそのマシーンにロードする。これによって、各マシーンが行う修正をそのアーキテクチャ及びオペレーティングシステムに基づき僅かに異なるように最適化することができ、更に全ての他の類似の修正と整合を取ることができる。
【００４３】
別の構成では、特定のマシーン、例えばＭ１は修正されていないコードをロードし、全ての他のマシーンＭ２、Ｍ３．．．Ｍｎは、オリジナルのアプリケーションコードを削除し修正されたバージョンをロードするよう修正を行う。
【００４４】
全ての事例において、供給は、ブランチ（すなわち、Ｍ２がＭ１、Ｍ３、Ｍ４などの各々に直接提供する）又はカスケード或いはシーケンシャル（すなわち、Ｍ２はＭ１に供給し、次にＭ１がＭ３に供給し、次いで、Ｍ３がＭ４に供給する、以下同じ）とすることができる。
【００４５】
更に別の構成では、Ｍ１からＭｎまでのマシーンは追加のマシーン（図示せず）に全てのロード要求を送ることができ、該追加マシーンは、アプリケーションプログラムを実行しておらず、前述の方法のいずれかを介して修正を行い、修正ルーチンをマシーンＭ１からＭｎまでの各々に返し、次いで、マシーンＭ１からＭｎがこの修正ルーチンをローカルにロードする。この構成では、マシーンＭ１からＭｎは、修正ルーチンを各マシーンに返すこの追加のマシーンに全ロード要求を転送する。この追加のマシーンによって行われる修正は、本発明の範囲内で保護される修正形態の全てを含むことができる。
【００４６】
コンピュータ関連技術に熟練した人であれば、コンピュータコードで修正を作製する際に使用される少なくとも４つの技術を認識することになる。第１は、オリジナル（ソース）言語で修正を行うことである。第２は、オリジナルコード（例えばＪＡＶＡでの）を中間表現（又は中間言語）に変換することである。この変換を行うと、修正がなされ、次いで逆変換される。これは、修正されたＪＡＶＡコードの要求結果をもたらす。
【００４７】
第３の可能性は、マシーンコードに（直接又は前述の中間言語を介して）変換することである。次にマシーンコードは修正された後、ロードされ実行される。第４の可能性は、オリジナルコードを中間表現に変換することであり、この中間表現は次に修正され、その後マシーンコードに変換される。
【００４８】
本発明は、全ての４つの修正ルートと、更にこのようなルートの２つ、３つ、又は４つ全部の組み合わせを包含する。
【００４９】
ここで図１４を参照すると、ＪＡＶＡ仮想マシーンとして動作する単一の従来技術のコンピュータの概略図が示されている。このように、マシーン（種々の製造業者のいずれか１つによって生産され、種々の異なる言語のいずれか１つで動作するオペレーティングシステムを有する）は、アプリケーションプログラム５０の特定の言語、この場合はＪＡＶＡ言語で動作することができる。すなわち、ＪＡＶＡ仮想マシーン７２は、ＪＡＶＡ言語でコード５０を動作させることができ、マシーン製造業者及びマシーンの内部詳細に関係なくＪＡＶＡアーキテクチャを利用することができる。
【００５０】
ＪＡＶＡ言語では、初期化ルーチン＜ｃｌｉｎｉｔ＞は、所与のクラスファイル５０Ａがロードされたときにだけ起こる。しかしながら、初期化ルーチン＜ｉｎｉｔ＞は、例えば新しいオブジェクト５０Ｘ、５０Ｙ、及び５０Ｚが作成される度に頻繁に起こる。更に、単一のクラス５０Ａ及び３つのオブジェクト５０Ｘ−５０Ｚを有する図１４に示されたアプリケーションプログラムにおいて、第１のクラス５０Ａがまずロードされ、次に第１オブジェクト５０Ｘがロードされ、次いで第２オブジェクト５０Ｙがロードされ、最後に第３オブジェクト５０Ｚがロードされるように、クラスはオブジェクトの前にロードされる。ここで図１４にあるように、単一のコンピュータ又はマシーン７２だけが存在し、従って、ロード手順中に動作することが意図された初期化ルーチンの実行中にどのような矛盾も不一致も発生しない。
【００５１】
しかしながら、図８に示される構成（及び図２２−２４）では、複数の個々のコンピュータ又はマシーンＭ１、Ｍ２．．．Ｍｎが備えられ、その各々は、通信ネットワーク５３を介して相互接続されており、その各々はモディファイアー５１を備え、更に共通のアプリケーションプログラム５０がロードされる。本質的に、モディファイアー５１は、個々のマシーンＭ１、Ｍ２．．．Ｍｎの各々に対する同一のメモリ構造及びコンテンツを複製しなければならない。従って、このようなコンピューティング環境では個々のマシーンＭ１、Ｍ２．．．Ｍｎの各々が矛盾の無い様式で初期化されるのを保証することが必要とされることになる。図５のモディファイアー５１の修正関数は、図８のＤＲＴ７１によって提供される。
【００５２】
矛盾の無い初期化を保証するために、アプリケーションプログラム５０は、初期化ルーチンを定義するプログラムステップを検出するために精査される。この精査は、ロード前又はロード手順７５中のいずれか、或いはロード手順７５後（且つ関連した対応アプリケーションコードの実行前）でも行うことができる。これは、用語「コンパイル」が通常はコード又は言語において、例えばソースからオブジェクトコード、或いは１つの言語から別の言語への変更を伴うことを理解した上で、コンパイル手順に形容することができる。しかしながら、本実施例では、用語「コンパイル」（及びその文法的に等価なもの）は、同じコード又は言語内に限定されず、修正形態を含み包含することができる。
【００５３】
結果として、上述の精査において、＜ｃｌｉｎｉｔ＞ルーチンが最初に探され、見つかった場合には、修正コード（通常は幾つかの命令）が挿入されて修正＜ｃｌｉｎｉｔ＞ルーチンを生じさせる。この修正ルーチンは、マシーンのうちの１つ、例えばＪＶＭ＃１にクラス５０Ａをロードし、このようなクラス５０Ａが存在する他のマシーンＭ２．．．Ｍｎ全てとその現在の状態を伝えることになる。幾つかの異なるモードが存在することで、この修正及びロードを実行することができる。
【００５４】
従って、１つのモードでは、ロードマシーン上のＤＲＴ７１（この実施例ではＪＶＭ＃１）は、第１クラス５０Ａが既に初期化されているかどうかを他のマシーン全てのＤＲＴ７１／２．．．７１／ｎに尋ねる。この質問に対する答えがイエスである場合、標準的な初期化手順はターンオフ又は無効にされる。答えがノーである場合、標準的な初期化手順が行われ、その手順の間に生じた結果としての変更が、図８の矢印８３によって示される全ての他のマシーンに伝達される。
【００５５】
類似の手順は、オブジェクト、例えば５０Ｘ、５０Ｙ、又は５０Ｚがロードされる各場合に起こる。ここでＤＲＴ７１／１は、問合せの結果として、当該特定のオブジェクト（例えばオブジェクト５０Ｙ）が既に他のマシーンＭ２．．．Ｍｎにロードされ、次いでＤＲＴ７１／１がオブジェクト初期化ルーチンを実行して、他のマシーンＭ２．．．Ｍｎの各々に等価のオブジェクト（便宜上ピアオブジェクトと呼ぶ場合がある）を初期値のコピーと共にロードすることを識別しない。しかしながら、当該オブジェクト５０Ｙが既に他のマシーンに存在しているとＤＲＴ７１／１が判定した場合、標準的な初期化機能は無効にされ、ローカルコピーが現在値のコピーによって作成される。同様に、望ましい結果をもたらす種々の方法が存在する。
【００５６】
図１５で分かるように、図８の一般的構成に対する修正は、マシーンＭ１、Ｍ２．．．Ｍｎがこれまでと同じであり、全マシーンＭ１、Ｍ２．．．Ｍｎに対して同時に同じアプリケーションプログラム５０を実行するようにされる。しかしながら、以前の構成は、ハウスキーピング機能、及び特に構造、資産、及び資源の初期化を好都合に供給できるサーバーマシーンＸを備えることによって修正される。このようなサーバーマシーンＸは、その計算負荷が低いため、ＰＣなどの低価格製品コンピュータとすることができる。図１５の破線で示されるように、２つのサーバーマシーンＸ及びＸ＋１は、システムの全体的な信頼性を高める冗長性の目的で設けられる。２つのこのようなサーバーマシーンＸ及びＸ＋１が設けられる場合、これらは、クラスタ形態の二重マシーンのように動作するのが好ましい。追加のマシーンＸ＋１は、図１５の破線で示される任意選択のものである。
【００５７】
計算負荷をマシーンＭ１、Ｍ２．．．Ｍｎ全体にわたって分散させることができるときには、サーバーマシーンＸを設ける必要はない。或いは、１つのマシーンで動作されるデータベース（マスタ／スレーブタイプのオペレーション）は、ハウスキーピング機能に用いることができる。
【００５８】
図１６は、実行されるべき好ましい一般手順を示している。ロードステップ１６１の開始後、実行される命令が順番に考慮され、ステップ１６２で示されるように全ての初期化ルーチンが検出される。ＪＡＶＡ言語では、これらは、＜ｉｎｉｔ＞及び＜ｃｌｉｎｉｔ＞ルーチン（又はＪＡＶＡ用語におけるメソッド）である。他の言語は異なる項を使用する。
【００５９】
初期化ルーチンがステップ１６２で検出された場合、ステップ１６３で、通常は別の命令をルーチンに挿入することにより修正される。或いは、修正命令をルーチンの前に挿入することもできる。修正ステップ１６３が完了すると、ステップ１６４で示されるようにロード手順に進む。
【００６０】
図１７は、修正の特定の形式を示している。ステップ１７１でルーチンの開始後、ステップ１７２において、初期化されることになる構造、資産、又は資源（ＪＡＶＡではクラス又はオブジェクトと呼ばれる）は、全マシーンによりグローバルに利用可能な名前又はタグが割り当てられる。これは、図１５のサーバーマシーンＸによって維持されるテーブルを介して最も好都合に行われる。このテーブルはまた、初期化されることになるクラス又はオブジェクトの状態を含む。
【００６１】
図１７に示されるように、他の箇所（すなわち、ロードを実行しているマシーン以外のマシーン）でグローバル名が未だ初期化されていないことをステップ１７３及び１７４が判定した場合には、そのグローバル名は作成される最初のこのようなオブジェクト又はクラスであるので、この判定は、ステップ１７６の実行により該オブジェクト又はクラスを通常の方式で初期化することができることを意味する。
【００６２】
しかしながら、他の箇所でグローバル名が既に利用されていることをステップ１７３及び１７４が判定した場合には、これは、別のマシーンがこのクラス又はオブジェクトを既に初期化していたことを意味する。その結果、ステップ１７５を実行することにより、正規の初期化ルーチンはその全体が中止される。
【００６３】
図１８は、図１５のサーバーマシーンＸへのロードマシーン（Ｍ１、Ｍ２．．．Ｍｎの１つ）によって行われる問合せを示す。ロードマシーンのオペレーションは、ステップ１８２によって示されるようにマシーンＸから返信が受信されるまでステップ１８１で示されるように一時的に中断される。
【００６４】
図１９は、図１８のステップ１８１のような問合せに応答した図１５のマシーンＸによって実行される動作を示している。初期化状態は、ステップ１９２及び１９３で判定され、既に初期化されている場合には、その作用への応答がステップ１９４を実行することによって問合せをしているマシーンに送信される。同様に、初期化状態が初期化されていない場合には、対応する返信がステップ１９５及び１９６を実行することによって送信される。次いで、ステップ１８２によって作成された待機中の問合せマシーンは、これに伴い応答することができる。
【００６５】
付属の添付書を参照する。
添付書Ａ１−Ａ１０は、フィールドに関する実際のコードを示す。
添付書Ｂ１は、修正されていない＜ｃｌｉｎｉｔ＞命令からの一般的コードフラグメントである。
添付書Ｂ２は、修正された＜ｃｌｉｎｉｔ＞命令に関する等価物である。
添付書Ｂ３は、修正されていない＜ｉｎｉｔ＞命令からの一般的なコードフラグメントである。
添付書Ｂ４は、修正された＜ｉｎｉｔ＞命令に関する等価物である。
更に、添付書Ｂ５は、添付書Ｂ２のコードの代替物である。
添付書Ｂ６は、添付書Ｂ４のコードの代替物である。
更に、添付書Ｂ７は、ＩｎｉｔＣｌｉｅｎｔのソースコードであり、関連クラス又はオブジェクトの初期化状態について「初期化サーバー」に問い合わせる。
添付書Ｂ８は、ＩｎｉｔＳｅｒｖｅｒのソースコードであり、ＩｎｉｔＣｌｉｅｎｔによる初期化状態問合せを受け取り、これに応じて対応する状態を返す。
同様に添付書Ｂ９は、添付書Ｂ１−Ｂ６の実施例の前／後で使用される例示的なアプリケーションのソースコードである。
【００６６】
ここで図２０を参照すると、添付書Ｂ１のコードフラグメントから添付書Ｂ２のコードフラグメントに変換するためのクラスに関する＜ｃｌｉｎｉｔ＞ルーチンの修正に従った手順が示されている。アプリケーションプログラム５０のＪＡＶＡ仮想マシーン７２上への初期ロードはステップ２０１で始まり、ステップ２０２の実行により、コードの各行が精査され、＜ｃｌｉｎｉｔ＞ルーチンを表わす命令を検出する。検出されると、ステップ２０３を実行することにより、＜ｃｌｉｎｉｔ＞ルーチンが添付書Ｂ２に示されるように修正される。ステップ２０４に示されるように、修正が完了後、ロード手順は次に進む。
【００６７】
添付書Ｂ１及びＢ２はそれぞれ、＜ｃｌｉｎｉｔ＞命令の前と後の抜粋である。本方法に追加される修正コードは、下線で強調されている。添付書Ｂ１のオリジナルコードサンプルでは、＜ｃｌｉｎｉｔ＞方法は、それ自体の新しいオブジェクトを作成し、これを「ｔｈｉｓＴｅｓｔ」と呼ばれるメモリロケーション（フィールド）に書き込む。従って、分散環境でのクラスロードを管理することなく、各マシーンは、異なるオブジェクトによって同じ共有メモリロケーション（フィールド）を再び初期化することになる。明らかに、これは、ロードされるアプリケーションプログラムのプログラマーが発生を予測したものではない。
【００６８】
そこで、ＤＲＴを利用することで、アプリケーションコードは、＜ｃｌｉｎｉｔ＞方法を変更することによってマシーンにロードされるように修正される。行われた変更（下線で強調されている）は、＜ｃｌｉｎｉｔ＞方法が実行する初期命令である。これらの追加命令は、このクラスのロード状態に対応した真又は偽のいずれかを返すｉｓＡｌｒｅａｄｙＬｏａｄｅｄ（）法を呼び出すことにより、このクラスが既にロードされているかどうかをチェックする。
【００６９】
ＤＲＴのｉｓＡｌｒｅａｄｙＬｏａｄｅｄ（）法は、このクラスのロード状態の判定に使用される、例えばクラスの名前、又はこのクラスを表わすクラスオブジェクト、或いは全マシーンにわたってこのクラスを表わす固有の数字である、このクラスの一意の識別子を表わす引数（添付書Ｂ５及びＢ６を参照されたい）を任意選択的に取ることができる。このように、ＤＲＴは、各クラスの一意の識別子を使用してｉｓＡｌｒｅａｄｙＬｏａｄｅｄテーブルの正確な記録に照会することにより、複数のクラスのどれが既にロードされたており、どれがロードしていないかに関して混同することなく同時に複数のクラスのロードをサポートすることができる。
【００７０】
ＤＲＴは、クラスのロード状態を幾つかの方法で判定することができる。好ましくは、ＤＲＴは、このクラスがロードされる場合に順に各マシーンに尋ねることができ、いずれかのマシーンが真を返信した場合には真を返し、そうでなければ偽を返す。或いは、ローカルマシーン上のＤＲＴは、共有記録テーブル（場合によっては別個のマシーン（例えばマシーンＸ）上）、或いはローカルマシーン上の一貫性のある共有記録テーブル、或いはデータベース）に照会し、このクラスが既にロードされているかどうかを判定することができる。
【００７１】
ＤＲＴが偽を返した場合には、これは、このクラスが分散型環境内のいずれのマシーンにもこれまでロードされていないことを意味し、従って、この実行は、第１のもの及びオリジナルと見なすことになる。この結果、ＤＲＴは、共有記録テーブル内のこのクラスの「ｉｓＡｌｒｅａｄｙＬｏａｄｅｄ」記録を真にするよう更新し、現在のマシーンを含む全ての他のマシーン上でｉｓＡｌｒｅａｄｙＬｏａｄｅｄの全ての後続の呼出しがここで真を返すようにする必要がある。従って、ＤＲＴ．ｉｓＡｌｒｅａｄｙＬｏａｄｅｄ（）が偽を返す場合には、修正された＜ｃｌｉｎｉｔ＞法は、オリジナルコードブロックに進み、オリジナルコードブロックは挿入された３つの命令をたどる。
【００７２】
他方、ＤＲＴが真を返す場合には、これは、このクラスがロードされたクラスの共有記録テーブル内に記録されているように、分散型環境で既にロードされていることを意味する。このような場合、オリジナルコードブロックは、既に初期化されたメモリロケーションなどに上書きされるように実行されるＮＯＴである。従って、ＤＲＴが真を返す場合、挿入された３つの命令によってオリジナルコードの実行が阻止され、アプリケーションプログラムに直ぐに戻る。
【００７３】
オブジェクトに関する＜ｉｎｉｔ＞ルーチンの同等の手順が図２１に示されており、ここでステップ２１２及び２１３は、図２０のステップ２０２及び２０３に相当する。この結果、添付書Ｂ３のコードは添付書Ｂ４のコードに変換されることになる。
【００７４】
＜ｃｌｉｎｉｔ＞で使用されたのと類似の修正が、＜ｉｎｉｔ＞において使用される。アプリケーションプログラムの＜ｉｎｉｔ＞ブロック（又は＜ｃｌｉｎｉｔ＞ではない複数のものが存在することができるような、複数のブロック）は、ステップ２１２で示されるように検出され、ステップ２１３で示されるように修正されて、分散型環境全体にわたり一貫して動作する。
【００７５】
添付書Ｂ３の実施例では、アプリケーションプログラムの＜ｉｎｉｔ＞命令は、ロード時間のタイムスタンプによってメモリロケーション（フィールド）を初期化する。アプリケーションは、例えばこのオブジェクトが作成された時点を記録するのにこれを使用することができる。明らかに、ピアオブジェクトが種々の時間にロードできる分散型環境において、最初にロードされたピアオブジェクトのタイムスタンプが後のピアオブジェクトによって間違いなく上書きされないようにするための特別な処置が必要である。
【００７６】
修正実施後の逆アセンブル命令シーケンスが、添付書Ｂ４に説明されており、修正／挿入された命令が下線で強調されている。＜ｃｌｉｎｉｔ＞修正とは異なる＜ｉｎｉｔ＞修正では、修正命令は、最初ではなく「呼出し特別」命令の後に配置する必要があることが多い。この理由は、ＪＡＶＡ仮想マシーン仕様によって判定される。他の言語は、類似の設計の僅かな差異を有することが多い。
【００７７】
初期化が既に行われているかどうかを確認するためにテストの基本的概念が与えられ、初期化が行われていない場合には初期化を実行し、行われている場合には、これ以上の初期化は実行されず、すなわち、この概念を実行できる幾つかの種々の方法が存在する。
【００７８】
第１の実施形態において、特定のマシーン、例えばマシーンＭ２は、自己にクラス又はオブジェクトをロードし、次いで他のマシーンＭ１、Ｍ３．．．Ｍｎの各々に（順次又は同時に）ロードする。「マスタ／スレーブ」と呼ぶことができるこの構成では、マシーンＭ１、Ｍ３．．．Ｍｎの各々がマシーンＭ２によって与えられるものをロードする。
【００７９】
この「マスタ／スレーブ」構成の変形形態では、マシーンＭ２は、マシーンＭ２に対し修正されていない形式で＜ｃｌｉｎｉｔ＞ルーチンをロードし、次いで初期化ルーチンを全て削除することによってクラスを修正し、修正されたクラスを他のマシーンにロードする。従ってこの場合、修正は、初期化ルーチンのバイパスではなく、１つを除いた全マシーンでのルーチンの削除である。
【００８０】
更に別の実施形態において、各マシーンは初期化ルーチンを受け取るが、これを修正しそのマシーンに対し修正ルーチンをロードする。これによって、各マシーンによって行われる修正がそのアーキテクチャ及びオペレーティングシステムに基づいて僅かに異なるように最適化され、全ての他の類似の修正と一貫性があるようにすることができる。
【００８１】
別の構成では、特定のマシーン、例えばＭ１はクラスをロードし、全ての他のマシーンＭ２、Ｍ３．．．Ｍｎは、初期化ルーチンを削除し修正されたバージョンをロードするよう修正を行う。
【００８２】
全ての事例において、供給は、ブランチ（すなわち、Ｍ２がＭ１、Ｍ３、Ｍ４などの各々に直接提供する）又はカスケード或いはシーケンシャル（すなわち、Ｍ２はＭ１に印加し、次にＭ１がＭ３に供給し、次いでＭ３がＭ４に供給する、以下同じ）とすることができる。
【００８３】
更に別の構成では、初期マシーン、例えばＭ２は初期ロードを実行し、次いでマシーンＭ２によってロードされたクラスの全てをリストするテーブルを作成することができる。次に、このテーブルは、全ての他のマシーンに（ブランチ又はカスケード方式のいずれかで）送られる。次いで、Ｍ２以外のマシーンがテーブルにリストされたクラスへのアクセスを必要とする場合には、マシーンは、要求をＭ２に送り、必要な情報を提供する。従って、マシーンＭｎに提供された情報は、一般にはマシーンＭ２にロードされた初期状態とは異なる。
【００８４】
上記の状況の下では、クラスがロードされるその度毎にインクリメントされるカウンタを伴うことがテーブルの各エントリに必要とされる。従って、データが要求された場合、クラスコンテンツ及び対応するカウンタのカウントの両方が要求に応じて転送される。この「オンデマンド」モードは、各コンピュータのオーバーヘッドを増大させるが、コンピュータを相互接続する通信ネットワーク上のトラフィック量を低減する。
【００８５】
更に別の構成では、マシーンＭ１からＭｎは、追加のマシーンＸ（図１５）に全ロード要求を送ることができ、該追加のマシーンＸは、前述の方法のいずれかによって修正を行い、修正されたクラスをマシーンＭ１からＭｎの各々に返して、次いでこのクラスをローカルにロードする。この構成では、マシーンＭ１からＭｎは、あらゆるクラスについての記録のテーブルも保持しない代わりに、マシーンＸに全ロード要求を転送し、該マシーンＸは、ロードされたクラスのテーブルを保持し、所与のクラスがマシーンＭ１からＭｎにロードされたのが始めてであるかどうかに応じて修正クラスを各マシーンに返す。マシーンＸによって行われた修正は、本発明の範囲内で保護される修正のいずれをも含むことができる。
【００８６】
コンピュータ関連技術に熟練した人であれば、コンピュータコードで修正を作成する際に使用される４つの技術を認識することになる。第１は、オリジナル（ソース）言語で修正を行うことである。第２は、オリジナルコード（例えばＪＡＶＡでの）を中間表現（又は中間言語）に変換することである。この変換を行うと、修正がなされ、次いで逆変換される。これは、修正されたＪＡＶＡコードの要求結果をもたらす。
【００８７】
第３の可能性は、マシーンコードに（直接又は前述の中間言語を介して）変換することである。次にマシーンコードは修正された後、ロードされ実行される。第４の可能性は、オリジナルコードを中間表現に変換することであり、この中間表現は次に修正され、その後マシーンコードに変換される。
【００８８】
本発明は、全ての４つの修正ルートと、更にこのようなルートの２つ、３つ、又は４つ全部の組み合わせを包含する。
【００８９】
ここで図２２−２４を参照すると、２つのラップトップコンピュータ１０１及び１０２が示されている。コンピュータ１０１及び１０２は、必ずしも同一でなくともよく、実際には、１つはＩＢＭ又はＩＢＭクローンで、他方がＡＰＰＬＥコンピュータとすることができる。コンピュータ１０１及び１０２は、２つのモニタ１０５、１１５及び２つのキーボード１０６、１１６と、単一のマウス１０７とを有する。２つのマシーン１０１、１０２は、単一の同軸ケーブル又はツイストペアケーブル３１４手段によって相互接続されている。
【００９０】
２つのシンプルアプリケーションプログラムは、マシーン１０１、１０２の各々にダウンロードされ、このプログラムは上述のようにロードされるときに修正される。この実施形態において、第１アプリケーションは、シンプル計算器プログラムであり、モニタ１０５上に表示される計算器１０８のイメージをもたらす。第２プログラムは、異なる色であり且つ矩形ボックス３１０内をランダムに動き回る４つのカラーブロック１０９を表示するグラフィックプログラムである。同様にロード後に、ボックス３１０はモニタ１０５上に表示される。各アプリケーションはブロック１０９がモニタ１０５上でランダムに移動しているように独立して動作すると同時に、計算器１０８内の数字は数学的演算子（加算又は乗算など）と共に（マウス１０７を用いて）選択され、計算器１０８が結果を表示することができるようになる。
【００９１】
マウス１０７を用いて、ボックス３１０を「把持」し、これを右方向にモニタ１０５を越えてモニタ１１５上に移動させ、図２３に示された状況に到るようにすることができる。この構成では、計算器アプリケーションがマシーン１０１上で処理されている間、ボックス３１０の表示をもたらすグラフィックアプリケーションはマシーン１０２上で処理されている。
【００９２】
しかしながら、図２４に示されるようにマウス１０７を用いることで、図２３に示されるように計算器１０８を右側にドラッグし、計算器１０８の一部をモニタ１０５、１１５の各々で表示させることができる。同様に、図２３に示されるボックス３１０は、マウス１０７を用いて左側にドラッグすることができ、その結果、ボックス３１０は図２４に示されるようにモニタ１０５、１１５の各々で部分的に表示されるようになる。この構成では、計算器オペレーションの部分は、マシーン１０１とマシーン１０２の一部上で実行されていると同時に、グラフィックアプリケーションの部分はマシーン１０１で実行されており、残りはマシーン１０２で実行されている。
【００９３】
上記は、本発明の幾つかの実施形態だけを説明しており、当業者であれば本発明の範囲から逸脱することなく本発明に対し修正を行うことができる点は明らかであろう。例えば、ＪＡＶＡへの言及は、ＪＡＶＡ言語と更にＪＡＶＡプラットフォーム及びアーキテクチャの両方を含む。
【００９４】
プログラミング技術に熟練した者であれば、付加的なコード又は命令が既存のコード又は命令セットに挿入されてこれを修正する場合、既存のコード又は命令セットは、オフセット、分岐、属性、マークアップ、及び同様のものが作成されるような追加の修正（例えば、シーケンシャル命令の再ナンバリングによって）を必要とする場合があることを認識するであろう。
【００９５】
同様に、ＪＡＶＡ言語でのメモリロケーションは、例えばフィールド及びアレイタイプの両方を含む。上記の説明は、フィールドを扱っており、アレイタイプに必要な変更は、本質的に同じ準用である。また本発明は、Ｍｉｃｒｏｓｏｆｔ．ＮＥＴプラットフォーム及びアーキテクチャ（ＶｉｓｕａｌＢａｓｉｃ、ＶｉｓｕａｌＣ／Ｃ++、及びＣ＃）のＦＯＲＴＲＡＮ、Ｃ／Ｃ++、ＣＯＢＯＬ、ＢＡＳＩＣなどを含むＪＡＶＡに類似したプログラミング言語（手続き、宣言、及びオブジェクト指向を含む）に対して等しく適用可能である。
【００９６】
ＪＡＶＡ初期化ルーチンのコードが修正される上述の実施形態は、各マシーンＭ１．．．Ｍｎのランタイムシステム（例えば、Ｃ及びＪＡＶＡで記述されたＪＡＶＡ  ＨＯＴＳＰＯＴ  ＶＩＲＴＵＡＬ  ＭＡＣＨＩＮＥ）又はオペレーティングシステム（例えば、Ｃ及びアセンブラで記述されたＬＩＮＵＸ）のいずれかがＪＡＶＡ初期化ルーチンを呼び出すことになる仮定に基づく。ＪＡＶＡ初期化ルーチンを未修正のままにし、その代わりにＪＡＶＡ初期化ルーチンを呼び出すＬＩＮＵＸ又はＨＯＴＳＰＯＴルーチンを修正することが可能であり、その結果、オブジェクト又はクラスが既にロードされている場合には、ＪＡＶＡ初期化ルーチンは呼び出されない。このような構成を包含するために、用語「初期化ルーチン」は、ＪＡＶＡ初期化ルーチンと、ＪＡＶＡ初期化ルーチンとＪＡＶＡ初期化ルーチンを呼び出すか又は開始するＬＩＮＵＸ又はＨＯＴＳＰＯＴコードフラグメントの「組み合わせ」の両方がその範囲に含まれることになると理解すべきである。
【００９７】
本明細書で使用される用語オブジェクト及びクラスは、ＪＡＶＡ環境から生じたものであり、ダイナミックリンクライブラリ（ＤＬＬ）、或いはオブジェクトコードパッケージ、或いは関数ユニット又はメモリロケーションのような異なる環境から派生した類似語を包含するものとする。
【００９８】
本明細書で使用される用語「備える」（及びその文法的変形形態）は、「有する」又は「含む」といった包括的な意味で使用され、「だけからなる」という排他的意味では使用されない。
【００９９】
著作権表示
本特許出願は、著作権保護の下にある資料を含む。著作権所有者（出願人）は、審査の目的で公的に利用可能な関連する特許庁ファイルからこの特許明細書又は関連資料を複製することに異議はないが、これ以外は如何なるものも無断転載が禁じられている。特に、種々の命令は、著作権所有者によって具体的に文書による承諾なしにコンピュータに入力されるべきではない。
【０１００】
添付書Ａ
以下は、ＪＡＶＡ言語でのプログラムリストである。
Ａ１．この第１の抜粋は、修正コードの一部である。これは、コードアレイをサーチし、ｐｕｔｓｔａｔｉｃ命令（ｏｐｃｏｄｅ１７８）を見つけると、修正を実行する。
// START
byte[] code =  Code_attribute.code;       // Bytecode of a given method in a 
// given classfile.
int code_length = Code_attribute.code_length;
int DRT = 99;         // Location of the CONSTANT_Methodref_info for the 
// DRT.alert() method.
for (int i=0; i<code_length; i++){
if ((code[i] & 0xff) == 179){               // Putstatic instruction.
System.arraycopy(code, i+3, code, i+6, code_length-(i+3));
code[i+3] = (byte) 184;       // Invokestatic instruction for the 
// DRT.alert() method.
code[i+4] = (byte) ((DRT >>> 8) & 0xff);
code[i+5] = (byte) (DRT & 0xff);
}
}
// END
【０１０１】
Ａ２．この第２の抜粋は、ＤＲＴ．ａｌｅｒｔ（）法の一部である。これは、呼び出されたときのＤＲＴ．ａｌｅｒｔ（）法の本体である。
// START
public static void alert(){
synchronized (ALERT_LOCK){
ALERT_LOCK.notify();     // Alerts a waiting DRT thread in the background.
}
}
// END
【０１０２】
Ａ３．この第３の抜粋は、ＤＲＴ送信の一部である。このコードフラグメントは、別々のスレッドのＤＲＴを示しており、通知された後にネットワーク全体に値を送信する。
// START
MulticastSocket ms = DRT.getMulticastSocket();          // The multicast socket 
// used by the DRT for 
// communication.
byte nameTag = 33;          // This is the “name tag” on the network for this 
// field.
Field field = modifiedClass.getDeclaredField(“myField1”);     // Stores 
// the field 
// from the 
// modified 
// class.
// In this example, the field is a byte field.
while (DRT.isRunning()){
synchronized (ALERT_LOCK){
ALERT_LOCK.wait();     // The DRT thread is waiting for the alert 
// method to be called.
byte[] b = new byte[]{nameTag, field.getByte(null)};     // Stores 
// the 
// nameTag 
// and the 
// value 
// of the
// field from 
// the modified 
// class in a 
// buffer.
DatagramPacket dp = new DatagramPacket(b, 0, b.length);
ms.send(dp);               // Send the buffer out across the network.
}
}
// END
【０１０３】
Ａ４．第４の抜粋は、ＤＲＴ受信の一部である。これは、ネットワークを通じてＤＲＴ送信警報を受信するためのコードのフラグメントである。
// START
MulticastSocket ms = DRT.getMulticastSocket();  // The multicast socket 
// used by the DRT for 
// communication.
DatagramPacket dp = new DatagramPacket(new byte[2], 0, 2);
byte nameTag = 33;          // This is the “name tag” on the network for this 
// field.
Field field = modifiedClass.getDeclaredField(“myField1”);     // Stores the 
// field from 
// the modified 
// class.
// In this example, the field is a byte field.
while (DRT.isRunning){
ms.receive(dp);      // Receive the previously sent buffer from the network.
byte[] b = dp.getData();
if (b[0] == nameTag){          // Check the nametags match.
field.setByte(null, b[1]); // Write the value from the network packet 
// into the field location in memory.
}
}
// END
【０１０４】
Ａ５．第５の抜粋は、修正が行われる前の例示的なアプリケーションである。
Method void setValues(int, int)
0 iload_1
1 putstatic #3 <Field int staticValue>
4 aload_0
5 iload_2
6 putfield #2 <Field int instanceValue>
9 return
【０１０５】
Ａ６．第６の抜粋は、修正が実行された後の５と同様の例示的なアプリケーションである。修正は下線で強調されている。
Method void setValues(int, int)
0 iload_1
1 putstatic #3 <Field int staticValue>
4 ldc #4 <String “example”>
6 iconst_0
7 invokestatic #5 <Method void alert(java.lang.Object, int)>
10 aload_0
11 iload_2
12 putfield #2 <Field int instanceValue>
15 aload_0
16 iconst_1
17 invokestatic #5 <Method void alert(java.lang.Object, int)>
20 return
【０１０６】
Ａ７．第７の抜粋は、抜粋５及び６で使用された例示的なアプリケーションのソースコードである。
import java.lang.*;
public class example{
/** Shared static field. */
public static int staticValue = 0;
/** Shared instance field. */
public int instanceValue = 0;
/** Example method that writes to memory (instance field). */
public void setValues(int a, int b){
staticValue = a;
instanceValue = b;
}
}
【０１０７】
Ａ８．第８の抜粋は、「分散ランタイム」をアラートし変更された値を伝播するＦｉｅｌｄＡｌｅｒｔのソースコードである。
import java.lang.*;
import java.util.*;
import java.net.*;
import java.io.*;
public class FieldAlert{
/** Table of alerts. */
public final static Hashtable alerts = new Hashtable();
/** Object handle. */
public Object reference = null;
/** Table of field alerts for this object. */
public boolean[] fieldAlerts = null;
/** Constructor. */
public FieldAlert(Object o, int initialFieldCount){
reference = o;
fieldAlerts = new boolean[initialFieldCount];
}
/** Called when an application modifies a value. (Both objects and 
classes) */
public static void alert(Object o, int fieldID){
// Lock the alerts table.
synchronized (alerts){
FieldAlert alert = (FieldAlert) alerts.get(o);
if (alert == null){        // This object hasn't been alerted already, 
// so add to alerts table.
alert = new FieldAlert(o, fieldID + 1);
alerts.put(o, alert);
}
if (fieldID >= alert.fieldAlerts.length){
// Ok, enlarge fieldAlerts array.
boolean[] b = new boolean[fieldID+1];
System.arraycopy(alert.fieldAlerts, 0, b, 0, 
alert.fieldAlerts.length);
alert.fieldAlerts = b;
}
// Record the alert.
alert.fieldAlerts[fieldID] = true;
// Mark as pending.
FieldSend.pending = true;         // Signal that there is one or more 
// propagations waiting.
// Finally, notify the waiting FieldSend thread(s)
if (FieldSend.waiting){
FieldSend.waiting = false;
alerts.notify();
}
}
}
}
【０１０８】
Ａ９．第９の抜粋は、ＦｉｅｌｄＡｌｅｒｔを介してアラートされた変更値を伝播するＦｉｅｌｄＳｅｎｄのソースコードである。
import java.lang.*;
import java.lang.reflect.*;
import java.util.*;
import java.net.*;
import java.io.*;
public class FieldSend implements Runnable{
/** Protocol specific values. */
public final static int CLOSE = -1;
public final static int NACK = 0;
public final static int ACK = 1;
public final static int PROPAGATE_OBJECT = 10;
public final static int PROPAGATE_CLASS = 20;
/** FieldAlert network values. */
public final static String group = 
System.getProperty(“FieldAlert_network_group”);
public final static int port = 
Integer.parseInt(System.getProperty(“FieldAlert_network_port”));
/** Table of global ID's for local objects. (hashcode-to-globalID 
mappings) */
public final static Hashtable objectToGlobalID = new Hashtable();
/** Table of global ID's for local classnames. (classname-to-globalID 
mappings) */
public final static Hashtable classNameToGlobalID = new Hashtable();
/** Pending. True if a propagation is pending. */
public static boolean pending = false;
/** Waiting. True if the FieldSend thread(s) are waiting. */
public static boolean waiting = false;
/** Background send thread. Propagates values as this thread is alerted 
to their alteration. */
public void run(){
System.out.println(“FieldAlert_network_group=” + group);
System.out.println(“FieldAlert_network_port=” + port);
try{
// Create a DatagramSocket to send propagated field values.
DatagramSocket datagramSocket =
new DatagramSocket(port, InetAddress.getByName(group));
// Next, create the buffer and packet for all transmissions.
byte[] buffer = new byte[512];            // Working limit of 512 bytes
// per packet.
DatagramPacket datagramPacket =
new DatagramPacket(buffer, 0, buffer.length);
while (!Thread.interrupted()){
Object[] entries = null;
// Lock the alerts table.
synchronized (FieldAlert.alerts){
// Await for an alert to propagate something.
while (!pending){
waiting = true;
FieldAlert.alerts.wait();
waiting = false;
}
pending = false;
entries = FieldAlert.alerts.entrySet().toArray();
// Clear alerts once we have copied them.
FieldAlert.alerts.clear();
}
// Process each object alert in turn.
for (int i=0; i<entries.length; i++){
FieldAlert alert = (FieldAlert) entries[i];
int index = 0;
datagramPacket.setLength(buffer.length);
Object reference = null;
if (alert.reference instanceof String){
// PROPAGATE_CLASS field operation.
buffer[index++] = (byte) ((PROPAGATE_CLASS >> 24) & 0xff);
buffer[index++] = (byte) ((PROPAGATE_CLASS >> 16) & 0xff);
buffer[index++] = (byte) ((PROPAGATE_CLASS >> 8) & 0xff);
buffer[index++] = (byte) ((PROPAGATE_CLASS >> 0) & 0xff);
String name = (String) alert.reference;
int length = name.length();
buffer[index++] = (byte) ((length >> 24) & 0xff);
buffer[index++] = (byte) ((length >> 16) & 0xff);
buffer[index++] = (byte) ((length >> 8) & 0xff);
buffer[index++] = (byte) ((length >> 0) & 0xff);
byte[] bytes = name.getBytes();
System.arraycopy(bytes, 0, buffer, index, length);
index += length;
}else{       // PROPAGATE_OBJECT field operation.
buffer[index++] =
(byte) ((PROPAGATE_OBJECT >> 24) & 0xff);
buffer[index++] =
(byte) ((PROPAGATE_OBJECT >> 16) & 0xff);
buffer[index++] = (byte) ((PROPAGATE_OBJECT >> 8) & 0xff);
buffer[index++] = (byte) ((PROPAGATE_OBJECT >> 0) & 0xff);
int globalID = ((Integer)
objectToGlobalID.get(alert.reference)).intValue();
buffer[index++] = (byte) ((globalID >> 24) & 0xff);
buffer[index++] = (byte) ((globalID >> 16) & 0xff);
buffer[index++] = (byte) ((globalID >> 8) & 0xff);
buffer[index++] = (byte) ((globalID >> 0) & 0xff);
reference = alert.reference;
}
// Use reflection to get a table of fields that correspond to 
// the field indexes used internally.
Field[] fields = null;
if (reference == null){
fields = FieldLoader.loadClass((String)
alert.reference).getDeclaredFields();
}else{
fields = alert.reference.getClass().getDeclaredFields();
}
// Now encode in batch mode the fieldID/value pairs.
for (int j=0; j<alert.fieldAlerts.length; j++){
if (alert.fieldAlerts[j] == false)
continue;
buffer[index++] = (byte) ((j >> 24) & 0xff);
buffer[index++] = (byte) ((j >> 16) & 0xff);
buffer[index++] = (byte) ((j >> 8) & 0xff);
buffer[index++] = (byte) ((j >> 0) & 0xff);
// Encode value.
Class type = fields[j].getType();
if (type == Boolean.TYPE){
buffer[index++] =(byte) 
(fields[j].getBoolean(reference)? 1 : 0);
}else if (type == Byte.TYPE){
buffer[index++] = fields[j].getByte(reference);
}else if (type == Short.TYPE){
short v = fields[j].getShort(reference);
buffer[index++] = (byte) ((v >> 8) & 0xff);
buffer[index++] = (byte) ((v >> 0) & 0xff);
}else if (type == Character.TYPE){
char v = fields[j].getChar(reference);
buffer[index++] = (byte) ((v >> 8) & 0xff);
buffer[index++] = (byte) ((v >> 0) & 0xff);
}else if (type == Integer.TYPE){
int v = fields[j].getInt(reference);
buffer[index++] = (byte) ((v >> 24) & 0xff);
buffer[index++] = (byte) ((v >> 16) & 0xff);
buffer[index++] = (byte) ((v >> 8) & 0xff);
buffer[index++] = (byte) ((v >> 0) & 0xff);
}else if (type == Float.TYPE){
int v = Float.floatToIntBits(
fields[j].getFloat(reference));
buffer[index++] = (byte) ((v >> 24) & 0xff);
buffer[index++] = (byte) ((v >> 16) & 0xff);
buffer[index++] = (byte) ((v >> 8) & 0xff);
buffer[index++] = (byte) ((v >> 0) & 0xff);
}else if (type == Long.TYPE){
long v = fields[j].getLong(reference);
buffer[index++] = (byte) ((v >> 56) & 0xff);
buffer[index++] = (byte) ((v >> 48) & 0xff);
buffer[index++] = (byte) ((v >> 40) & 0xff);
buffer[index++] = (byte) ((v >> 32) & 0xff);
buffer[index++] = (byte) ((v >> 24) & 0xff);
buffer[index++] = (byte) ((v >> 16) & 0xff);
buffer[index++] = (byte) ((v >> 8) & 0xff);
buffer[index++] = (byte) ((v >> 0) & 0xff);
}else if (type == Double.TYPE){
long v = Double.doubleToLongBits(
fields[j].getDouble(reference));
buffer[index++] = (byte) ((v >> 56) & 0xff);   
buffer[index++] = (byte) ((v >> 48) & 0xff);
buffer[index++] = (byte) ((v >> 40) & 0xff);
buffer[index++] = (byte) ((v >> 32) & 0xff);
buffer[index++] = (byte) ((v >> 24) & 0xff);
buffer[index++] = (byte) ((v >> 16) & 0xff);
buffer[index++] = (byte) ((v >> 8) & 0xff);
buffer[index++] = (byte) ((v >> 0) & 0xff);
}else{
throw new AssertionError(“Unsupported type.”);
}
}
// Now set the length of the datagrampacket.
datagramPacket.setLength(index);
// Now send the packet.
datagramSocket.send(datagramPacket);
}
}
}catch (Exception e){
throw new AssertionError(“Exception: ” + e.toString());
}
}
}
【０１０９】
Ａ１０．第１０の抜粋は、ＦｉｅｌｄＳｅｎｄを介して送信される伝播された変更値を受信するＦｉｅｌｄＲｅｃｅｉｖｅのソースコードである。
import java.lang.*;
import java.lang.reflect.*;
import java.util.*;
import java.net.*;
import java.io.*;
public class FieldReceive implements Runnable{
/** Protocol specific values. */
public final static int CLOSE = -1;
public final static int NACK = 0;
public final static int ACK = 1;
public final static int PROPAGATE_OBJECT = 10;
public final static int PROPAGATE_CLASS = 20;
/** FieldAlert network values. */
public final static String group = 
System.getProperty(“FieldAlert_network_group”);
public final static int port = 
Integer.parseInt(System.getProperty(“FieldAlert_network_port”));
/** Table of global ID's for local objects. (globalID-to-hashcode 
mappings) */
public final static Hashtable globalIDToObject = new Hashtable();
/** Table of global ID's for local classnames. (globalID-to-classname 
mappings) */
public final static Hashtable globalIDToClassName = new Hashtable();
/** Called when an application is to acquire a lock. */
public void run(){
System.out.println(“FieldAlert_network_group=” + group);
System.out.println(“FieldAlert_network_port=” + port);
try{
// Create a DatagramSocket to send propagated field values from
MulticastSocket multicastSocket = new MulticastSocket(port);
multicastSocket.joinGroup(InetAddress.getByName(group));
// Next, create the buffer and packet for all transmissions.
byte[] buffer = new byte[512];                 // Working limit of 512
// bytes per packet.
DatagramPacket datagramPacket =
new DatagramPacket(buffer, 0, buffer.length);
while (!Thread.interrupted()){
// Make sure to reset length.
datagramPacket.setLength(buffer.length);
// Receive the next available packet.
multicastSocket.receive(datagramPacket);
int index = 0, length = datagramPacket.getLength();
// Decode the command.
int command = (int) (((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16) 
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
if (command == PROPAGATE_OBJECT){     // Propagate operation for 
// object fields.
// Decode global id.
int globalID = (int) (((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16) 
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
// Now, need to resolve the object in question.
Object reference = globalIDToObject.get(
new Integer(globalID));
// Next, get the array of fields for this object.
Field[] fields = reference.getClass().getDeclaredFields();
while (index < length){
// Decode the field id.
int fieldID = (int) (((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
// Determine value length based on corresponding field 
// type.
Field field = fields[fieldID];
Class type = field.getType();
if (type == Boolean.TYPE){
boolean v = (buffer[index++] == 1 ? true : false);
field.setBoolean(reference, v);
}else if (type == Byte.TYPE){
byte v = buffer[index++];
field.setByte(reference, v);
}else if (type == Short.TYPE){
short v = (short) (((buffer[index++] & 0xff) << 8) 
| (buffer[index++] & 0xff));
field.setShort(reference, v);
}else if (type == Character.TYPE){
char v = (char) (((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setChar(reference, v);
}else if (type == Integer.TYPE){
int v = (int) (((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setInt(reference, v);
}else if (type == Float.TYPE){
int v = (int) (((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setFloat(reference, Float.intBitsToFloat(v));
}else if (type == Long.TYPE){
long v = (long) (((buffer[index++] & 0xff) << 56)
| ((buffer[index++] & 0xff) << 48)
| ((buffer[index++] & 0xff) << 40)
| ((buffer[index++] & 0xff) << 32)
| ((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setLong(reference, v);
}else if (type == Double.TYPE){
long v = (long) (((buffer[index++] & 0xff) << 56)
| ((buffer[index++] & 0xff) << 48)
| ((buffer[index++] & 0xff) << 40)
| ((buffer[index++] & 0xff) << 32)
| ((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setDouble(reference, Double.longBitsToDouble(v));
}else{
throw new AssertionError(“Unsupported type.”);
}
}
}else if (command == PROPAGATE_CLASS){    // Propagate an update 
// to class fields.
// Decode the classname.
int nameLength = (int) (((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
String name = new String(buffer, index, nameLength);
index += nameLength;
// Next, get the array of fields for this class.
Field[] fields = 
FieldLoader.loadClass(name).getDeclaredFields();
// Decode all batched fields included in this propagation 
// packet.
while (index < length){
// Decode the field id.
int fieldID = (int) (((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
// Determine field type to determine value length.
Field field = fields[fieldID];
Class type = field.getType();
if (type == Boolean.TYPE){
boolean v = (buffer[index++] == 1 ? true : false);
field.setBoolean(null, v);
}else if (type == Byte.TYPE){
byte v = buffer[index++];
field.setByte(null, v);
}else if (type == Short.TYPE){
short v = (short) (((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setShort(null, v);
}else if (type == Character.TYPE){
char v = (char) (((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setChar(null, v);
}else if (type == Integer.TYPE){
int v = (int) (((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setInt(null, v);
}else if (type == Float.TYPE){
int v = (int) (((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setFloat(null, Float.intBitsToFloat(v));
}else if (type == Long.TYPE){
long v = (long) (((buffer[index++] & 0xff) << 56)
| ((buffer[index++] & 0xff) << 48)
| ((buffer[index++] & 0xff) << 40)
| ((buffer[index++] & 0xff) << 32)
| ((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setLong(null, v);
}else if (type == Double.TYPE){
long v = (long) (((buffer[index++] & 0xff) << 56)
| ((buffer[index++] & 0xff) << 48)
| ((buffer[index++] & 0xff) << 40)
| ((buffer[index++] & 0xff) << 32)
| ((buffer[index++] & 0xff) << 24)
| ((buffer[index++] & 0xff) << 16)
| ((buffer[index++] & 0xff) << 8)
| (buffer[index++] & 0xff));
field.setDouble(null, Double.longBitsToDouble(v));
}else{       // Unsupported field type.
throw new AssertionError(“Unsupported type.”);
}
}
}
}
}catch (Exception e){
throw new AssertionError(“Exception: ” + e.toString());
}
}
}
【０１１０】
Ａ１１．ＦｉｅｌｄＬｏａｄｅｒ．ｊａｖａ
この抜粋は、ロードされているときにアプリケーションを修正するＦｉｅｌｄＬｏａｄｅｒのソースコードである。
import java.lang.*;
import java.io.*;
import java.net.*;
public class FieldLoader extends URLClassLoader{
public FieldLoader(URL[] urls){
super(urls);
}
protected Class findClass(String name)
throws ClassNotFoundException{
ClassFile cf = null;
try{
BufferedInputStream in =
new BufferedInputStream(findResource(
name.replace('.', '/').concat(“.class”)).openStream());
cf = new ClassFile(in);
}catch (Exception e){throw new ClassNotFoundException(e.toString());}
// Class-wide pointers to the ldc and alert index.
int ldcindex = -1;
int alertindex = -1;
for (int i=0; i<cf.methods_count; i++){
for (int j=0; j<cf.methods[i].attributes_count; j++){
if (!(cf.methods[i].attributes[j] instanceof Code_attribute))
continue;
Code_attribute ca = (Code_attribute) cf.methods[i].attributes[j];
boolean changed = false;
for (int z=0; z<ca.code.length; z++){
if ((ca.code[z][0] & 0xff) == 179){  // Opcode for a PUTSTATIC 
// instruction.
changed = true;
// The code below only supports fields in this class.
// Thus, first off, check that this field is local to this 
// class.
CONSTANT_Fieldref_info fi = (CONSTANT_Fieldref_info) 
cf.constant_pool[(int) (((ca.code[z][1] & 0xff) << 8) | 
(ca.code[z][2] & 0xff))];
CONSTANT_Class_info ci = (CONSTANT_Class_info) 
cf.constant_pool[fi.class_index];
String className = 
cf.constant_pool[ci.name_index].toString();
if (!name.equals(className)){
throw new AssertionError(“This code only supports fields ”
“local to this class”);
}
// Ok, now search for the fields name and index.
int index = 0;
CONSTANT_NameAndType_info ni = (CONSTANT_NameAndType_info) 
cf.constant_pool[fi.name_and_type_index];
String fieldName = 
cf.constant_pool[ni.name_index].toString();
for (int a=0; a<cf.fields_count; a++){
String fn = cf.constant_pool[
cf.fields[a].name_index].toString();
if (fieldName.equals(fn)){
index = a;
break;
}
}
// Next, realign the code array, making room for the 
// insertions.
byte[][] code2 = new byte[ca.code.length+3][];
System.arraycopy(ca.code, 0, code2, 0, z+1);
System.arraycopy(ca.code, z+1, code2, z+4,
ca.code.length-(z+1));
ca.code = code2;
// Next, insert the LDC_W instruction.
if (ldcindex == -1){
CONSTANT_String_info csi =
new CONSTANT_String_info(ci.name_index);
cp_info[] cpi = new cp_info[cf.constant_pool.length+1];
System.arraycopy(cf.constant_pool, 0, cpi, 0, 
cf.constant_pool.length);
cpi[cpi.length - 1] = csi;
ldcindex = cpi.length-1;
cf.constant_pool = cpi;
cf.constant_pool_count++;
}
ca.code[z+1] = new byte[3];
ca.code[z+1][0] = (byte) 19;
ca.code[z+1][1] = (byte) ((ldcindex >> 8) & 0xff);
ca.code[z+1][2] = (byte) (ldcindex & 0xff);
// Next, insert the SIPUSH instruction.
ca.code[z+2] = new byte[3];
ca.code[z+2][0] = (byte) 17;
ca.code[z+2][1] = (byte) ((index >> 8) & 0xff);
ca.code[z+2][2] = (byte) (index & 0xff);
// Finally, insert the INVOKESTATIC instruction.
if (alertindex == -1){
// This is the first time this class is encourtering the 
// alert instruction, so have to add it to the constant 
// pool.
cp_info[] cpi = new cp_info[cf.constant_pool.length+6];
System.arraycopy(cf.constant_pool, 0, cpi, 0, 
cf.constant_pool.length);
cf.constant_pool = cpi;
cf.constant_pool_count += 6;
CONSTANT_Utf8_info u1 =
new CONSTANT_Utf8_info(“FieldAlert”);
cf.constant_pool[cf.constant_pool.length-6] = u1;
CONSTANT_Class_info c1 = new CONSTANT_Class_info(
cf.constant_pool_count-6);
cf.constant_pool[cf.constant_pool.length-5] = c1;
u1 = new CONSTANT_Utf8_info(“alert”);
cf.constant_pool[cf.constant_pool.length-4] = u1;
u1 = new CONSTANT_Utf8_info(“(Ljava/lang/Object;I)V”);
cf.constant_pool[cf.constant_pool.length-3] = u1;
CONSTANT_NameAndType_info n1 =
new CONSTANT_NameAndType_info(
cf.constant_pool.length-4, cf.constant_pool.length-3);
cf.constant_pool[cf.constant_pool.length-2] = n1;
CONSTANT_Methodref_info m1 = new CONSTANT_Methodref_info(
cf.constant_pool.length-5, cf.constant_pool.length-2);
cf.constant_pool[cf.constant_pool.length-1] = m1;
alertindex = cf.constant_pool.length-1;
}
ca.code[z+3] = new byte[3];
ca.code[z+3][0] = (byte) 184;
ca.code[z+3][1] = (byte) ((alertindex >> 8) & 0xff);
ca.code[z+3][2] = (byte) (alertindex & 0xff);
// And lastly, increase the CODE_LENGTH and ATTRIBUTE_LENGTH 
// values.
ca.code_length += 9;
ca.attribute_length += 9;
}
}
// If we changed this method, then increase the stack size by one.
if (changed){
ca.max_stack++;               // Just to make sure.
}
}
}
try{
ByteArrayOutputStream out = new ByteArrayOutputStream();
cf.serialize(out);
byte[] b = out.toByteArray();
return defineClass(name, b, 0, b.length);
}catch (Exception e){
throw new ClassNotFoundException(name);
}
}
}
【０１１１】
Ａ１２．Ａｔｔｒｉｂｕｔｅ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のａｔｔｒｉｂｕｔｅ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** This abstract class represents all types of attribute_info 
*  that are used in the JVM specifications.
*  
*  All new attribute_info subclasses are to always inherit from this 
*  class.
*/
public abstract class attribute_info{
public int attribute_name_index;
public int attribute_length;
/** This is used by subclasses to register themselves
*  to their parent classFile.
*/
attribute_info(ClassFile cf){}
/** Used during input serialization by ClassFile only. */
attribute_info(ClassFile cf, DataInputStream in)
throws IOException{
attribute_name_index = in.readChar();
attribute_length = in.readInt();
} 
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
out.writeChar(attribute_name_index);
out.writeInt(attribute_length);
}
/** This class represents an unknown attribute_info that
*  this current version of classfile specification does
*  not understand.
*/
public final static class Unknown extends attribute_info{
byte[] info;
/** Used during input serialization by ClassFile only. */
Unknown(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
info = new byte[attribute_length];
in.read(info, 0, attribute_length);
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
super.serialize(out);
out.write(info, 0, attribute_length);
}
}
}
【０１１２】
Ａ１３．ＣｌａｓｓＦｉｌｅ．ｊａｖａ
ＣｌａｓｓＦｉｌｅ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
import java.util.*;
/** The ClassFile follows verbatim from the JVM specification.  */
public final class ClassFile {
public int magic;
public int minor_version;
public int major_version;
public int constant_pool_count;
public cp_info[] constant_pool;
public int access_flags;
public int this_class;
public int super_class;
public int interfaces_count;
public int[] interfaces;
public int fields_count;
public field_info[] fields;
public int methods_count;
public method_info[] methods;
public int attributes_count;
public attribute_info[] attributes;
/** Constructor. Takes in a byte stream representation and transforms
*  each of the attributes in the ClassFile into objects to allow for
*  easier manipulation. 
*/
public ClassFile(InputStream ins)
throws IOException{
DataInputStream in = (ins instanceof DataInputStream ?
(DataInputStream) ins : new DataInputStream(ins));
magic = in.readInt();
minor_version = in.readChar();
major_version = in.readChar();
constant_pool_count = in.readChar();
constant_pool = new cp_info[constant_pool_count];
for (int i=1; i<constant_pool_count; i++){
in.mark(1);
int s = in.read();
in.reset();
switch (s){
case 1:
constant_pool[i] = new CONSTANT_Utf8_info(this, in);
break;
case 3:
constant_pool[i] = new CONSTANT_Integer_info(this, in);
break;
case 4:
constant_pool[i] = new CONSTANT_Float_info(this, in);
break;
case 5:
constant_pool[i] = new CONSTANT_Long_info(this, in);
i++;  
break;
case 6:
constant_pool[i] = new CONSTANT_Double_info(this, in);
i++;
break;
case 7:
constant_pool[i] = new CONSTANT_Class_info(this, in);
break;
case 8:
constant_pool[i] = new CONSTANT_String_info(this, in);
break;
case 9:
constant_pool[i] = new CONSTANT_Fieldref_info(this, in);
break;
case 10:
constant_pool[i] = new CONSTANT_Methodref_info(this, in);
break;
case 11:
constant_pool[i] =
new CONSTANT_InterfaceMethodref_info(this, in);
break;
case 12:
constant_pool[i] = new CONSTANT_NameAndType_info(this, in);
break;
default:
throw new ClassFormatError(“Invalid ConstantPoolTag”);
}
}
access_flags = in.readChar();
this_class = in.readChar();
super_class = in.readChar();
interfaces_count = in.readChar();
interfaces = new int[interfaces_count];
for (int i=0; i<interfaces_count; i++)
interfaces[i] = in.readChar();
fields_count = in.readChar();
fields = new field_info[fields_count];
for (int i=0; i<fields_count; i++) {
fields[i] = new field_info(this, in);
}
methods_count = in.readChar();
methods = new method_info[methods_count];
for (int i=0; i<methods_count; i++) {                        
methods[i] = new method_info(this, in);      
}
attributes_count = in.readChar();
attributes = new attribute_info[attributes_count];
for (int i=0; i<attributes_count; i++){
in.mark(2);
String s = constant_pool[in.readChar()].toString();
in.reset();
if (s.equals(“SourceFile”))
attributes[i] = new SourceFile_attribute(this, in);
else if (s.equals(“Deprecated”))
attributes[i] = new Deprecated_attribute(this, in);
else if (s.equals(“InnerClasses”)) 
attributes[i] = new InnerClasses_attribute(this, in);
else                  
attributes[i] = new attribute_info.Unknown(this, in);
}
}
/** Serializes the ClassFile object into a byte stream. */
public void serialize(OutputStream o)
throws IOException{
DataOutputStream out = (o instanceof DataOutputStream ? 
(DataOutputStream) o : new DataOutputStream(o));
out.writeInt(magic);
out.writeChar(minor_version);
out.writeChar(major_version);
out.writeChar(constant_pool_count);
for (int i=1; i<constant_pool_count; i++){
constant_pool[i].serialize(out);
if (constant_pool[i] instanceof CONSTANT_Long_info ||
constant_pool[i] instanceof CONSTANT_Double_info)
i++;
}
out.writeChar(access_flags);
out.writeChar(this_class);
out.writeChar(super_class);
out.writeChar(interfaces_count);
for (int i=0; i<interfaces_count; i++)
out.writeChar(interfaces[i]);
out.writeChar(fields_count);
for (int i=0; i<fields_count; i++)
fields[i].serialize(out);
out.writeChar(methods_count);
for (int i=0; i<methods_count; i++)
methods[i].serialize(out);
out.writeChar(attributes_count);
for (int i=0; i<attributes_count; i++)
attributes[i].serialize(out);    
// Flush the outputstream just to make sure.
out.flush();
}
}
【０１１３】
Ａ１４．Ｃｏｄｅ＿ａｔｔｒｉｂｕｔｅ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣｏｄｅ＿ａｔｔｒｉｂｕｔｅ構造を表わすためのコンビエンスクラス
import java.util.*;
import java.lang.*;
import java.io.*;
/**  
*  The code[] is stored as a 2D array.  */
public final class Code_attribute extends attribute_info{
public int max_stack;
public int max_locals;
public int code_length;
public byte[][] code;
public int exception_table_length;
public exception_table[] exception_table;
public int attributes_count;
public attribute_info[] attributes;
/** Internal class that handles the exception table. */
public final static class exception_table{
public int start_pc;
public int end_pc;
public int handler_pc;
public int catch_type;
}
/** Constructor called only by method_info. */
Code_attribute(ClassFile cf, int ani, int al, int ms, int ml, int cl, 
byte[][] cd, int etl, exception_table[] et, int ac, 
attribute_info[] a){
super(cf);
attribute_name_index = ani;
attribute_length = al;
max_stack = ms;
max_locals = ml;
code_length = cl;
code = cd;
exception_table_length = etl;
exception_table = et;
attributes_count = ac;
attributes = a;
}
/** Used during input serialization by ClassFile only. */
Code_attribute(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
max_stack = in.readChar();
max_locals = in.readChar();
code_length = in.readInt();
code = new byte[code_length][];
int i = 0;
for (int pos=0; pos<code_length; i++){
in.mark(1);
int s = in.read();
in.reset();
switch (s){
case 16:
case 18:
case 21:
case 22:
case 23:
case 24:
case 25:
case 54:
case 55:
case 56:
case 57:
case 58:
case 169:
case 188:
case 196:
code[i] = new byte[2];
break;
case 17:
case 19:
case 20:
case 132:
case 153:
case 154:
case 155:
case 156:
case 157:
case 158:
case 159:
case 160:
case 161:
case 162:
case 163:
case 164:
case 165:
case 166:
case 167:
case 168:
case 178:
case 179:
case 180:
case 181:
case 182:
case 183:
case 184:
case 187:
case 189:
case 192:
case 193:
case 198:
case 199:
case 209:
code[i] = new byte[3];
break;
case 197:
code[i] = new byte[4];
break;
case 185:
case 200:
case 201:
code[i] = new byte[5];
break;
case 170:{
int pad = 3 - (pos % 4);                             
in.mark(pad+13);                           // highbyte
in.skipBytes(pad+5);                       // lowbyte
int low = in.readInt();
code[i] =
new byte[pad + 13 + ((in.readInt() - low + 1) * 4)];
in.reset();
break;
}case 171:{
int pad = 3 - (pos % 4);
in.mark(pad+9);
in.skipBytes(pad+5);                             
code[i] = new byte[pad + 9 + (in.readInt() * 8)];
in.reset();
break;
}default:
code[i] = new byte[1]; 
}
in.read(code[i], 0, code[i].length);
pos += code[i].length;
}
// adjust the array to the new size and store the size 
byte[][] temp = new byte[i][];
System.arraycopy(code, 0, temp, 0, i);
code = temp;
exception_table_length = in.readChar();
exception_table =
new Code_attribute.exception_table[exception_table_length];
for (i=0; i<exception_table_length; i++){
exception_table[i] = new exception_table();
exception_table[i].start_pc = in.readChar();
exception_table[i].end_pc = in.readChar();
exception_table[i].handler_pc = in.readChar();
exception_table[i].catch_type = in.readChar();
}
attributes_count = in.readChar();
attributes = new attribute_info[attributes_count];
for (i=0; i<attributes_count; i++){
in.mark(2);
String s = cf.constant_pool[in.readChar()].toString();
in.reset();
if (s.equals(“LineNumberTable”))
attributes[i] = new LineNumberTable_attribute(cf, in);
else if (s.equals(“LocalVariableTable”))
attributes[i] = new LocalVariableTable_attribute(cf, in);
else
attributes[i] = new attribute_info.Unknown(cf, in);
}
}
/** Used during output serialization by ClassFile only.
*/
void serialize(DataOutputStream out)
throws IOException{
attribute_length = 12 + code_length +
(exception_table_length * 8);
for (int i=0; i<attributes_count; i++)
attribute_length += attributes[i].attribute_length + 6;
super.serialize(out);
out.writeChar(max_stack);
out.writeChar(max_locals);
out.writeInt(code_length);
for (int i=0, pos=0; pos<code_length; i++){
out.write(code[i], 0, code[i].length);
pos += code[i].length;
}
out.writeChar(exception_table_length);
for (int i=0; i<exception_table_length; i++){
out.writeChar(exception_table[i].start_pc);
out.writeChar(exception_table[i].end_pc);
out.writeChar(exception_table[i].handler_pc);
out.writeChar(exception_table[i].catch_type);
}      
out.writeChar(attributes_count);
for (int i=0; i<attributes_count; i++)
attributes[i].serialize(out);
}
}
【０１１４】
Ａ１５．ＣＯＳＴＡＮＴ＿Ｃｌａｓｓ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＳＴＡＮＴ＿Ｃｌａｓｓ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Class subtype of a constant pool entry.  */
public final class CONSTANT_Class_info extends cp_info{
/** The index to the name of this class. */
public int name_index = 0;
/** Convenience constructor. 
*/
public CONSTANT_Class_info(int index) {
tag = 7;
name_index = index;
}
/** Used during input serialization by ClassFile only. */
CONSTANT_Class_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 7)
throw new ClassFormatError();
name_index = in.readChar();
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
out.writeByte(tag);
out.writeChar(name_index);
}
}
【０１１５】
Ａ１６．ＣＯＮＳＴＡＮＴ＿Ｄｏｕｂｌｅ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＮＳＴＡＮＴ＿Ｄｏｕｂｌｅ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Double subtype of a constant pool entry. */ 
public final class CONSTANT_Double_info extends cp_info{
/** The actual value. */
public double bytes;
public CONSTANT_Double_info(double d){
tag = 6;
bytes = d;
}
/** Used during input serialization by ClassFile only. */
CONSTANT_Double_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 6)
throw new ClassFormatError();
bytes = in.readDouble();
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
out.writeByte(tag);
out.writeDouble(bytes);
long l = Double.doubleToLongBits(bytes);
}
}
【０１１６】
Ａ１７．ＣＯＮＳＴＡＮＴ＿Ｆｉｅｌｄｒｅｆ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＮＳＴＡＮＴ＿Ｆｉｅｌｄｒｅｆ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Fieldref subtype of a constant pool entry.  */
public final class CONSTANT_Fieldref_info extends cp_info{
/** The index to the class that this field is referencing to. */
public int class_index;
/** The name and type index this field if referencing to. */    
public int name_and_type_index;
/** Convenience constructor. */
public CONSTANT_Fieldref_info(int class_index, int name_and_type_index) {
tag = 9;
this.class_index = class_index;
this.name_and_type_index = name_and_type_index;
}
/** Used during input serialization by ClassFile only. */
CONSTANT_Fieldref_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 9)
throw new ClassFormatError();
class_index = in.readChar();
name_and_type_index = in.readChar();
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
out.writeByte(tag);
out.writeChar(class_index);
out.writeChar(name_and_type_index);
}
}
【０１１７】
Ａ１８．ＣＯＮＳＴＡＮＴ＿Ｆｌｏａｔ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＮＳＴＡＮＴ＿Ｆｌｏａｔ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Float subtype of a constant pool entry. */
public final class CONSTANT_Float_info extends cp_info{
/** The actual value. */
public float bytes;
public CONSTANT_Float_info(float f){
tag = 4;
bytes = f;
}
/** Used during input serialization by ClassFile only. */
CONSTANT_Float_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 4)
throw new ClassFormatError();
bytes = in.readFloat();
}
/** Used during output serialization by ClassFile only. */
public void serialize(DataOutputStream out)
throws IOException{
out.writeByte(4);
out.writeFloat(bytes);
}
}
【０１１８】
Ａ１９．ＣＯＮＳＴＡＮＴ＿Ｉｎｔｅｇｅｒ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＮＳＴＡＮＴ＿Ｉｎｔｅｇｅｒ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Integer subtype of a constant pool entry.  */
public final class CONSTANT_Integer_info extends cp_info{
/** The actual value. */
public int bytes;
public CONSTANT_Integer_info(int b) {
tag = 3;
bytes = b;
}
/** Used during input serialization by ClassFile only. */
CONSTANT_Integer_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 3)
throw new ClassFormatError();
bytes = in.readInt();
}
/** Used during output serialization by ClassFile only. */
public void serialize(DataOutputStream out)
throws IOException{
out.writeByte(tag);
out.writeInt(bytes);
}
}
【０１１９】
Ａ２０．ＣＯＮＳＴＡＮＴ＿ＩｎｔｅｒｆａｃｅＭｅｔｈｏｄｒｅｆ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＮＳＴＡＮＴ＿ＩｎｔｅｒｆａｃｅＭｅｔｈｏｄｒｅｆ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** InterfaceMethodref subtype of a constant pool entry.
*/
public final class CONSTANT_InterfaceMethodref_info extends cp_info{
/** The index to the class that this field is referencing to. */
public int class_index;
/** The name and type index this field if referencing to. */    
public int name_and_type_index;
public CONSTANT_InterfaceMethodref_info(int class_index,
int name_and_type_index) {
tag = 11;
this.class_index = class_index;
this.name_and_type_index = name_and_type_index;
}
/** Used during input serialization by ClassFile only. */
CONSTANT_InterfaceMethodref_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 11)
throw new ClassFormatError();
class_index = in.readChar();
name_and_type_index = in.readChar();
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
out.writeByte(tag);
out.writeChar(class_index);
out.writeChar(name_and_type_index);
}
}
【０１２０】
Ａ２１．ＣＯＮＳＴＡＮＴ＿Ｌｏｎｇ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＮＳＴＡＮＴ＿Ｌｏｎｇ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Long subtype of a constant pool entry.  */
public final class CONSTANT_Long_info extends cp_info{
/** The actual value. */
public long bytes;
public CONSTANT_Long_info(long b){
tag = 5;
bytes = b;
}
/** Used during input serialization by ClassFile only. */
CONSTANT_Long_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 5)
throw new ClassFormatError();
bytes = in.readLong();
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
out.writeByte(tag);
out.writeLong(bytes);
}
}
【０１２１】
Ａ２２．ＣＯＮＳＴＡＮＴ＿Ｍｅｔｈｏｄｒｅｆ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＮＳＴＡＮＴ＿Ｍｅｔｈｏｄｒｅｆ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Methodref subtype of a constant pool entry. 
*/
public final class CONSTANT_Methodref_info extends cp_info{
/** The index to the class that this field is referencing to. */
public int class_index;
/** The name and type index this field if referencing to. */   
public int name_and_type_index;
public CONSTANT_Methodref_info(int class_index, int name_and_type_index) {
tag = 10;
this.class_index = class_index;
this.name_and_type_index = name_and_type_index;
}
/** Used during input serialization by ClassFile only. */
CONSTANT_Methodref_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 10)
throw new ClassFormatError();
class_index = in.readChar();
name_and_type_index = in.readChar();
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
out.writeByte(tag);
out.writeChar(class_index);
out.writeChar(name_and_type_index);
}
}
【０１２２】
Ａ２３．ＣＯＮＳＴＡＮＴ＿ＮａｍｅＡｎｄＴｙｐｅ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＮＳＴＡＮＴ＿ＮａｍｅＡｎｄＴｙｐｅ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.io.*;
import java.lang.*;
/** NameAndType subtype of a constant pool entry. 
*/
public final class CONSTANT_NameAndType_info extends cp_info{
/** The index to the Utf8 that contains the name. */
public int name_index;
/** The index fo the Utf8 that constains the signature. */
public int descriptor_index;
public CONSTANT_NameAndType_info(int name_index, int descriptor_index) {
tag = 12;
this.name_index = name_index;
this.descriptor_index = descriptor_index;
}
/** Used during input serialization by ClassFile only. */
CONSTANT_NameAndType_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 12)
throw new ClassFormatError();
name_index = in.readChar();
descriptor_index = in.readChar();
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
out.writeByte(tag);
out.writeChar(name_index);
out.writeChar(descriptor_index);
}
}
【０１２３】
Ａ２４．ＣＯＮＳＴＡＮＴ＿Ｓｔｒｉｎｇ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＮＳＴＡＮＴ＿Ｓｔｒｉｎｇ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** String subtype of a constant pool entry. 
*/
public final class CONSTANT_String_info extends cp_info{
/** The index to the actual value of the string. */
public int string_index;
public CONSTANT_String_info(int value) {
tag = 8;
string_index = value;
}
/** ONLY TO BE USED BY CLASSFILE! */
public CONSTANT_String_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 8)
throw new ClassFormatError();
string_index = in.readChar();
}
/** Output serialization, ONLY TO BE USED BY CLASSFILE! */
public void serialize(DataOutputStream out)
throws IOException{
out.writeByte(tag);
out.writeChar(string_index);
}
}
【０１２４】
Ａ２５．ＣＯＮＳＴＡＮＴ＿Ｕｔｆ８＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣＯＮＳＴＡＮＴ＿Ｕｔｆ８＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.io.*;
import java.lang.*;
/** Utf8 subtype of a constant pool entry. 
*  We internally represent the Utf8 info byte array 
*  as a String.
*/
public final class CONSTANT_Utf8_info extends cp_info{
/** Length of the byte array. */
public int length;
/** The actual bytes, represented by a String. */
public String bytes;
/** This constructor should be used for the purpose
*  of part creation. It does not set the parent 
*  ClassFile reference.
*/
public CONSTANT_Utf8_info(String s) {
tag = 1;
length = s.length(); 
bytes = s;
}
/** Used during input serialization by ClassFile only. */
public CONSTANT_Utf8_info(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
if (tag != 1)
throw new ClassFormatError();
length = in.readChar();
byte[] b = new byte[length];
in.read(b, 0, length);
// WARNING: String constructor is deprecated.
bytes = new String(b, 0, length);
}
/** Used during output serialization by ClassFile only. */
public void serialize(DataOutputStream out)
throws IOException{
out.writeByte(tag);
out.writeChar(length);
// WARNING: Handling of String coversion here might be problematic.
out.writeBytes(bytes);
}
public String toString(){
return bytes;
}
}
【０１２５】
Ａ２６．ＣｏｎｓｔａｎｔＶａｌｕｅ＿ａｔｔｒｉｂｕｔｅ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＣｏｎｓｔａｎｔＶａｌｕｅ＿ａｔｔｒｉｂｕｔｅ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Attribute that allows for initialization of static variables in 
*  classes. This attribute will only reside in a field_info struct.
*/
public final class ConstantValue_attribute extends attribute_info{
public int constantvalue_index;
public ConstantValue_attribute(ClassFile cf, int ani, int al, int cvi){
super(cf);
attribute_name_index = ani;
attribute_length = al;
constantvalue_index = cvi;
}
public ConstantValue_attribute(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
constantvalue_index = in.readChar();
}
public void serialize(DataOutputStream out)
throws IOException{
attribute_length = 2;
super.serialize(out);
out.writeChar(constantvalue_index);
}
}
【０１２６】
Ａ２７．ｃｐ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のｃｐ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Represents the common interface of all constant pool parts
*  that all specific constant pool items must inherit from. 
*
*/
public abstract class cp_info{
/** The type tag that signifies what kind of constant pool
*  item it is */
public int tag;
/** Used for serialization of the object back into a bytestream. */    
abstract void serialize(DataOutputStream out) throws IOException;
/** Default constructor. Simply does nothing. */
public cp_info() {} 
/** Constructor simply takes in the ClassFile as a reference to 
*  it's parent
*/
public cp_info(ClassFile cf) {}
/** Used during input serialization by ClassFile only. */
cp_info(ClassFile cf, DataInputStream in)
throws IOException{
tag = in.readUnsignedByte();
}
}
【０１２７】
Ａ２８．Ｄｅｐｒｅｃａｔｅｄ＿ａｔｔｒｂｉｕｔｅ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＤｅｐｒｅｃａｔｅｄ＿ａｔｔｒｂｉｕｔｅ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** A fix attributed that can be located either in the ClassFile, 
*  field_info or the method_info attribute. Mark deprecated to 
*  indicate that the method, class or field has been superceded. 
*/
public final class Deprecated_attribute extends attribute_info{
public Deprecated_attribute(ClassFile cf, int ani, int al){
super(cf);
attribute_name_index = ani;
attribute_length = al;
}
/** Used during input serialization by ClassFile only. */
Deprecated_attribute(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
}
}
【０１２８】
Ａ２９．Ｅｘｃｅｐｔｉｏｎｓ＿ａｔｔｒｉｂｕｔｅ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＥｘｃｅｐｔｉｏｎｓ＿ａｔｔｒｉｂｕｔｅ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** This is the struct where the exceptions table are located.
*  <br><br>
*  This attribute can only appear once in a method_info struct. 
*/
public final class Exceptions_attribute extends attribute_info{
public int number_of_exceptions;
public int[] exception_index_table;
public Exceptions_attribute(ClassFile cf, int ani, int al, int noe,
int[] eit){
super(cf);
attribute_name_index = ani;
attribute_length = al;
number_of_exceptions = noe;
exception_index_table = eit;
}
/** Used during input serialization by ClassFile only. */
Exceptions_attribute(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
number_of_exceptions = in.readChar();
exception_index_table = new int[number_of_exceptions];
for (int i=0; i<number_of_exceptions; i++)
exception_index_table[i] = in.readChar();
}
/** Used during output serialization by ClassFile only. */
public void serialize(DataOutputStream out)
throws IOException{
attribute_length = 2 + (number_of_exceptions*2);
super.serialize(out);
out.writeChar(number_of_exceptions);
for (int i=0; i<number_of_exceptions; i++)
out.writeChar(exception_index_table[i]);
}
}
【０１２９】
Ａ３０．ｆｉｅｌｄ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のｆｉｅｌｄ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/**   Represents the field_info structure as specified in the JVM specification. 
*/
public final class field_info{
public int access_flags;
public int name_index;
public int descriptor_index;
public int attributes_count;
public attribute_info[] attributes;
/** Convenience constructor. */
public field_info(ClassFile cf, int flags, int ni, int di){
access_flags = flags;
name_index = ni;
descriptor_index = di;
attributes_count = 0;
attributes = new attribute_info[0];
}
/** Constructor called only during the serialization process. 
*  <br><br> 
*  This is intentionally left as package protected as we
*  should not normally call this constructor directly.
*  <br><br>
*  Warning: the handling of len is not correct (after String s =...)
*/
field_info(ClassFile cf, DataInputStream in)
throws IOException{
access_flags = in.readChar();
name_index = in.readChar();
descriptor_index = in.readChar();
attributes_count = in.readChar();
attributes = new attribute_info[attributes_count];
for (int i=0; i<attributes_count; i++){
in.mark(2);
String s = cf.constant_pool[in.readChar()].toString();
in.reset();
if (s.equals(“ConstantValue”))
attributes[i] = new ConstantValue_attribute(cf, in);
else if (s.equals(“Synthetic”))
attributes[i] = new Synthetic_attribute(cf, in);
else if (s.equals(“Deprecated”))
attributes[i] = new Deprecated_attribute(cf, in);
else
attributes[i] = new attribute_info.Unknown(cf, in);
}
}
/** To serialize the contents into the output format.
*/
public void serialize(DataOutputStream out)
throws IOException{
out.writeChar(access_flags);
out.writeChar(name_index);
out.writeChar(descriptor_index);
out.writeChar(attributes_count);
for (int i=0; i<attributes_count; i++)
attributes[i].serialize(out);
}
}
【０１３０】
Ａ３１．ＩｎｎｅｒＣｌａｓｓｅｓ＿ａｔｔｒｉｂｕｔｅ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＩｎｎｅｒＣｌａｓｓｅｓ＿ａｔｔｒｉｂｕｔｅ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** A variable length structure that contains information about an 
*  inner class of this class. 
*/
public final class InnerClasses_attribute extends attribute_info{
public int number_of_classes;
public classes[] classes;
public final static class classes{
int inner_class_info_index;
int outer_class_info_index;
int inner_name_index;
int inner_class_access_flags;
}
public InnerClasses_attribute(ClassFile cf, int ani, int al,
int noc, classes[] c){
super(cf);
attribute_name_index = ani;
attribute_length = al;
number_of_classes = noc;
classes = c;
}
/** Used during input serialization by ClassFile only. */
InnerClasses_attribute(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
number_of_classes = in.readChar();
classes = new InnerClasses_attribute.classes[number_of_classes];
for (int i=0; i<number_of_classes; i++){            
classes[i] = new classes();
classes[i].inner_class_info_index = in.readChar();
classes[i].outer_class_info_index = in.readChar();
classes[i].inner_name_index = in.readChar();
classes[i].inner_class_access_flags = in.readChar();
}
}
/** Used during output serialization by ClassFile only. */
public void serialize(DataOutputStream out)
throws IOException{
attribute_length = 2 + (number_of_classes * 8);
super.serialize(out);
out.writeChar(number_of_classes);
for (int i=0; i<number_of_classes; i++){
out.writeChar(classes[i].inner_class_info_index);
out.writeChar(classes[i].outer_class_info_index);
out.writeChar(classes[i].inner_name_index);
out.writeChar(classes[i].inner_class_access_flags);
}
}
}
【０１３１】
Ａ３２．ＬｉｎｅＮｕｍｂｅｒＴａｂｌｅ＿ａｔｔｒｉｂｕｔｅ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＬｉｎｅＮｕｍｂｅｒＴａｂｌｅ＿ａｔｔｒｉｂｕｔｅ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Determines which line of the binary code relates to the 
*  corresponding source code. 
*/
public final class LineNumberTable_attribute extends attribute_info{
public int line_number_table_length;
public line_number_table[] line_number_table;
public final static class line_number_table{
int start_pc;
int line_number;
}
public LineNumberTable_attribute(ClassFile cf, int ani, int al, int lntl, 
line_number_table[] lnt){
super(cf);
attribute_name_index = ani;
attribute_length = al;
line_number_table_length = lntl;
line_number_table = lnt;
}
/** Used during input serialization by ClassFile only. */
LineNumberTable_attribute(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
line_number_table_length = in.readChar();
line_number_table = new LineNumberTable_attribute.line_number_table[line_number_table_length];
for (int i=0; i<line_number_table_length; i++){
line_number_table[i] = new line_number_table();
line_number_table[i].start_pc = in.readChar();
line_number_table[i].line_number = in.readChar();
}
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
attribute_length = 2 + (line_number_table_length * 4);
super.serialize(out);
out.writeChar(line_number_table_length);
for (int i=0; i<line_number_table_length; i++){
out.writeChar(line_number_table[i].start_pc);
out.writeChar(line_number_table[i].line_number);
}
}  
}
【０１３２】
Ａ３３．ＬｏｃａｌＶａｒｉａｂｌｅＴａｂｌｅ＿ａｔｔｒｉｂｕｔｅ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＬｏｃａｌＶａｒｉａｂｌｅＴａｂｌｅ＿ａｔｔｒｉｂｕｔｅ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** Used by debugger to find out how the source file line number is linked
*  to the binary code. It has many to one correspondence and is found in
*  the Code_attribute.
*/
public final class LocalVariableTable_attribute extends attribute_info{
public int local_variable_table_length;
public local_variable_table[] local_variable_table;
public final static class local_variable_table{
int start_pc;
int length;
int name_index;
int descriptor_index;
int index;
}
public LocalVariableTable_attribute(ClassFile cf, int ani, int al,
int lvtl, local_variable_table[] lvt){
super(cf);
attribute_name_index = ani;
attribute_length = al;
local_variable_table_length = lvtl;
local_variable_table = lvt;
}
/** Used during input serialization by ClassFile only. */
LocalVariableTable_attribute(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
local_variable_table_length = in.readChar();
local_variable_table = new LocalVariableTable_attribute.local_variable_table[local_variable_table_length];
for (int i=0; i<local_variable_table_length; i++){
local_variable_table[i] = new local_variable_table();
local_variable_table[i].start_pc = in.readChar();
local_variable_table[i].length = in.readChar();
local_variable_table[i].name_index = in.readChar();
local_variable_table[i].descriptor_index = in.readChar();
local_variable_table[i].index = in.readChar();
}
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
attribute_length = 2 + (local_variable_table_length * 10);
super.serialize(out);
out.writeChar(local_variable_table_length);
for (int i=0; i<local_variable_table_length; i++){
out.writeChar(local_variable_table[i].start_pc);
out.writeChar(local_variable_table[i].length);
out.writeChar(local_variable_table[i].name_index);
out.writeChar(local_variable_table[i].descriptor_index);
out.writeChar(local_variable_table[i].index);
}
}
}
【０１３３】
Ａ３４．ｍｅｔｈｏｄ＿ｉｎｆｏ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のｍｅｔｈｏｄ＿ｉｎｆｏ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** This follows the method_info in the JVM specification. 
*/
public final class method_info {
public int access_flags;
public int name_index;
public int descriptor_index;
public int attributes_count;
public attribute_info[] attributes;
/** Constructor. Creates a method_info, initializes it with 
*  the flags set, and the name and descriptor indexes given. 
*  A new uninitialized code attribute is also created, and stored
*  in the <i>code</i> variable.*/
public method_info(ClassFile cf, int flags, int ni, int di,
int ac, attribute_info[] a) {
access_flags = flags;
name_index = ni;
descriptor_index = di;
attributes_count = ac;
attributes = a;
}
/** This method creates a method_info from the current pointer in the
*  data stream. Only called by during the serialization of a complete 
*  ClassFile from a bytestream, not normally invoked directly.
*/
method_info(ClassFile cf, DataInputStream in)
throws IOException{
access_flags = in.readChar();
name_index = in.readChar();
descriptor_index = in.readChar();
attributes_count = in.readChar();
attributes = new attribute_info[attributes_count];
for (int i=0; i<attributes_count; i++){
in.mark(2);
String s = cf.constant_pool[in.readChar()].toString();
in.reset();
if (s.equals(“Code”))
attributes[i] = new Code_attribute(cf, in);
else if (s.equals(“Exceptions”))
attributes[i] = new Exceptions_attribute(cf, in);
else if (s.equals(“Synthetic”))
attributes[i] = new Synthetic_attribute(cf, in);
else if (s.equals(“Deprecated”))
attributes[i] = new Deprecated_attribute(cf, in);
else                               
attributes[i] = new attribute_info.Unknown(cf, in);
}
}
/** Output serialization of the method_info to a byte array.
*  Not normally invoked directly.
*/
public void serialize(DataOutputStream out)
throws IOException{
out.writeChar(access_flags);
out.writeChar(name_index);
out.writeChar(descriptor_index);
out.writeChar(attributes_count);
for (int i=0; i<attributes_count; i++)
attributes[i].serialize(out);
}
}
【０１３４】
Ａ３５．ＳｏｕｒｃｅＦｉｌｅ＿ａｔｔｒｉｂｕｔｅ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＳｏｕｒｃｅＦｉｌｅ＿ａｔｔｒｉｂｕｔｅ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** A SourceFile attribute is an optional fixed_length attribute in
*  the attributes table. Only located in the ClassFile struct only
*  once.
*/
public final class SourceFile_attribute extends attribute_info{
public int sourcefile_index;
public SourceFile_attribute(ClassFile cf, int ani, int al, int sfi){
super(cf);
attribute_name_index = ani;
attribute_length = al;
sourcefile_index = sfi;
}
/** Used during input serialization by ClassFile only. */
SourceFile_attribute(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
sourcefile_index = in.readChar();
}
/** Used during output serialization by ClassFile only. */
void serialize(DataOutputStream out)
throws IOException{
attribute_length = 2;
super.serialize(out);
out.writeChar(sourcefile_index);
}
}
【０１３５】
Ａ３６．Ｓｙｎｔｈｅｔｉｃ＿ａｔｔｒｉｂｕｔｅ．ｊａｖａ
ＣｌａｓｓＦｉｌｅｓ内のＳｙｎｔｈｅｔｉｃ＿ａｔｔｒｉｂｕｔｅ構造を表わすためのコンビエンスクラス
import java.lang.*;
import java.io.*;
/** A synthetic attribute indicates that this class does not have 
*  a generated code source. It is likely to imply that the code 
*  is generated by machine means rather than coded directly. This
*  attribute can appear in the classfile, method_info or field_info.
*  It is fixed length.
*/
public final class Synthetic_attribute extends attribute_info{
public Synthetic_attribute(ClassFile cf, int ani, int al){
super(cf);
attribute_name_index = ani;
attribute_length = al;
}
/** Used during output serialization by ClassFile only. */
Synthetic_attribute(ClassFile cf, DataInputStream in)
throws IOException{
super(cf, in);
}
}
【０１３６】
添付書Ｂ
B1
Method <clinit>
0 new #2 <Class test>
3 dup
4 invokespecial #3 <Method test()>
7 putstatic #4 <Field test thisTest>
10 return
B2
Method <clinit>
0 invokestatic #3 <Method boolean isAlreadyLoaded()>
3 ifeq 7
6 return
7 new #5 <Class test>
10 dup
11 invokespecial #6 <Method test()>
14 putstatic #7 <Field test thisTest>
17 return
B3
Method <init>
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 aload_0
5 invokestatic #2 <Method long currentTimeMillis()>
8 putfield #3 <Field long timestamp>
11 return
B4
Method <init>
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 invokestatic #2 <Method boolean isAlreadyLoaded()>
7 ifeq 13
10 return
11 aload_0
12 invokestatic #4 <Method long currentTimeMillis()>
15 putfield #5 <Field long timestamp>
18 return
B5
Method <clinit>
0 ldc #2 <String “test”>
2 invokestatic #3 <Method boolean isAlreadyLoaded(java.lang.String)>
5 ifeq 9
8 return
9 new #5 <Class test>
12 dup
13 invokespecial #6 <Method test()>
16 putstatic #7 <Field test thisTest>
19 return
B6
Method <init>
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 aload_0
5 invokestatic #2 <Method boolean isAlreadyLoaded(java.lang.Object)>
8 ifeq 13
11 return
12 aload_0
13 invokestatic #4 <Method long currentTimeMillis()>
16 putfield #5 <Field long timestamp>
19 return
【０１３７】
添付書Ｂ７
この抜粋は、関連したクラス又はオブジェクトの初期化状態を「初期化サーバー」に問い合わせるＩｎｉｔＣｌｉｅｎｔのソースコードである。
import java.lang.*;
import java.util.*;
import java.net.*;
import java.io.*;
public class InitClient{
/** Protocol specific values. */
public final static int CLOSE = -1;
public final static int NACK = 0;
public final static int ACK = 1;
public final static int INITIALIZE_CLASS = 10;
public final static int INITIALIZE_OBJECT = 20;
/** InitServer network values. */
public final static String serverAddress =
System.getProperty(“InitServer_network_address”);
public final static int serverPort =
Integer.parseInt(System.getProperty(“InitServer_network_port”));
/** Table of global ID's for local objects. (hashcode-to-globalID
mappings) */
public final static Hashtable hashCodeToGlobalID = new Hashtable();
/** Called when a object is being initialized. */
public static boolean isAlreadyLoaded(Object o){
// First of all, we need to resolve the globalID 
// for object 'o'.  To do this we use the hashCodeToGlobalID
// table.
int globalID = ((Integer) hashCodeToGlobalID.get(o)).intValue();
try{
// Next, we want to connect to the InitServer, which will inform us
// of the initialization status of this object.
Socket socket = new Socket(serverAddress, serverPort);
DataOutputStream out =
new DataOutputStream(socket.getOutputStream());
DataInputStream in =
new DataInputStream(socket.getInputStream());
// Ok, now send the serialized request to the InitServer.
out.writeInt(INITIALIZE_OBJECT);
out.writeInt(globalID);
out.flush();
// Now wait for the reply.
int status = in.readInt();      // This is a blocking call.  So we
// will wait until the remote side 
// sends something.
if (status == NACK){
throw new AssertionError(
“Negative acknowledgement. Request failed.”);
}else if (status != ACK){
throw new AssertionError(“Unknown acknowledgement: ”
+ status + “. Request failed.”);
}
// Next, read in a 32bit argument which is the count of previous 
// initializations.
int count = in.readInt();
// If the count is equal to 0, then this is the first 
// initialization, and hence isAlreadyLoaded should be false.
// If however, the count is greater than 0, then this is already 
// initialized, and thus isAlreadyLoaded should be true.
boolean isAlreadyLoaded = (count == 0 ? false : true);
// Close down the connection.
out.writeInt(CLOSE);
out.flush();
out.close();
in.close();
socket.close();                  // Make sure to close the socket.
// Return the value of the isAlreadyLoaded variable.
return isAlreadyLoaded;
}catch (IOException e){
throw new AssertionError(“Exception: ” + e.toString());
}
}
/** Called when a class is being initialized. */
public static boolean isAlreadyLoaded(String name){
try{
// First of all, we want to connect to the InitServer, which will 
// inform us of the initialization status of this class.
Socket socket = new Socket(serverAddress, serverPort);
DataOutputStream out =
new DataOutputStream(socket.getOutputStream());
DataInputStream in =
new DataInputStream(socket.getInputStream());
// Ok, now send the serialized request to the InitServer.
out.writeInt(INITIALIZE_CLASS);
out.writeInt(name.length());    // A 32bit length argument of 
// the String name.
out.write(name.getBytes(), 0, name.length());  // The byte-
// encoded 
// String name.
out.flush();
// Now wait for the reply.
int status = in.readInt(); // This is a blocking call. So we 
// will wait until the remote side 
// sends something.
if (status == NACK){
throw new AssertionError(
“Negative acknowledgement. Request failed.”);
}else if (status != ACK){
throw new AssertionError(“Unknown acknowledgement: ”
+ status + “. Request failed.”);
}
// Next, read in a 32bit argument which is the count of the 
// previous intializations.
int count = in.readInt();
// If the count is equal to 0, then this is the first 
// initialization, and hence isAlreadyLoaded should be false.
// If however, the count is greater than 0, then this is already 
// loaded, and thus isAlreadyLoaded should be true.
boolean isAlreadyLoaded = (count == 0 ? false : true);
// Close down the connection.
out.writeInt(CLOSE);
out.flush();
out.close();
in.close();
socket.close();   // Make sure to close the socket.
// Return the value of the isAlreadyLoaded variable.
return isAlreadyLoaded;
}catch (IOException e){
throw new AssertionError(“Exception: ” + e.toString());
}
}
}
【０１３８】
添付書Ｂ８
この抜粋は、ＩｎｉｔＣｌｉｅｎｔによる初期化状態問合せを受け取り、これに応じて対応する状態を返すＩｎｉｔＳｅｒｖｅｒのソースコードである。
import java.lang.*;
import java.util.*;
import java.net.*;
import java.io.*;
public class InitServer implements Runnable{
/** Protocol specific values */
public final static int CLOSE = -1;
public final static int NACK = 0;
public final static int ACK = 1;
public final static int INITIALIZE_CLASS = 10;
public final static int INITIALIZE_OBJECT= 20;
/** InitServer network values. */
public final static int serverPort = 20001;
/** Table of initialization records. */
public final static Hashtable initializations = new Hashtable();
/** Private input/output objects. */
private Socket socket = null;
private DataOutputStream outputStream;
private DataInputStream inputStream;
private String address;
public static void main(String[] s)
throws Exception{
System.out.println(“InitServer_network_address=”
+ InetAddress.getLocalHost().getHostAddress());
System.out.println(“InitServer_network_port=” + serverPort);
// Create a serversocket to accept incoming initialization operation 
// connections.
ServerSocket serverSocket = new ServerSocket(serverPort);
while (!Thread.interrupted()){
// Block until an incoming initialization operation connection.
Socket socket = serverSocket.accept();
// Create a new instance of InitServer to manage this 
// initialization operation connection.
new Thread(new InitServer(socket)).start();
}
}
/** Constructor. Initialize this new InitServer instance with necessary 
resources for operation. */
public InitServer(Socket s){
socket = s;
try{
outputStream = new DataOutputStream(s.getOutputStream());
inputStream = new DataInputStream(s.getInputStream());
address = s.getInetAddress().getHostAddress();
}catch (IOException e){
throw new AssertionError(“Exception: ” + e.toString());
}
}
/** Main code body. Decode incoming initialization operation requests and 
execute accordingly. */
public void run(){
try{
// All commands are implemented as 32bit integers.
// Legal commands are listed in the “protocol specific values” 
// fields above.
int command = inputStream.readInt();
// Continue processing commands until a CLOSE operation.
while (command != CLOSE){
if (command == INITIALIZE_CLASS){ // This is an 
// INITIALIZE_CLASS 
// operation.
// Read in a 32bit length field 'l', and a String name for 
// this class of length 'l'.
int length = inputStream.readInt();
byte[] b = new byte[length];
inputStream.read(b, 0, b.length);
String className = new String(b, 0, length);
// Synchronize on the initializations table in order to 
// ensure thread-safety.
synchronized (initializations){
// Locate the previous initializations entry for this 
// class, if any.
Integer entry = (Integer) initializations.get(className);
if (entry == null){ // This is an unknown class so 
// update the table with a 
// corresponding entry.
initializations.put(className, new Integer(1));
// Send a positive acknowledgement to InitClient, 
// together with the count of previous initializations 
// of this class - which in this case of an unknown 
// class must be 0.
outputStream.writeInt(ACK);
outputStream.writeInt(0);
outputStream.flush();
}else{               // This is a known class, so update 
// the count of initializations.
initializations.put(className,
new Integer(entry.intValue() + 1));
// Send a positive acknowledgement to InitClient, 
// together with the count of previous initializations
// of this class - which in this case of a known class 
// must be the value of “entry.intValue()”.
outputStream.writeInt(ACK);
outputStream.writeInt(entry.intValue());
outputStream.flush();
}
}
}else if (command == INITIALIZE_OBJECT){ // This is an 
// INITIALIZE_OBJECT 
// operation.
// Read in the globalID of the object to be initialized.
int globalID = inputStream.readInt();
// Synchronize on the initializations table in order to 
// ensure thread-safety.
synchronized (initializations){
// Locate the previous initializations entry for this
// object, if any.
Integer entry = (Integer) initializations.get(
new Integer(globalID));
if (entry == null){// This is an unknown object so 
// update the table with a 
// corresponding entry.
initializations.put(new Integer(globalID),
new Integer(1));
// Send a positive acknowledgement to InitClient, 
// together with the count of previous initializations
// of this object - which in this case of an unknown 
// object must be 0.
outputStream.writeInt(ACK);
outputStream.writeInt(0);
outputStream.flush();
}else{// This is a known object so update the 
// count of initializations.
initializations.put(new Integer(globalID), 
new Integer(entry.intValue() + 1));
// Send a positive acknowledgement to InitClient, 
// together with the count of previous initializations 
// of this object - which in this case of a known 
// object must be value “entry.intValue()”.
outputStream.writeInt(ACK);
outputStream.writeInt(entry.intValue());
outputStream.flush();
}
}
}else{// Unknown command.
throw new AssertionError(
“Unknown command. Operation failed.”);
}
// Read in the next command.
command = inputStream.readInt();
}
}catch (Exception e){
throw new AssertionError(“Exception: ” + e.toString());
}finally{
try{
// Closing down. Cleanup this connection.
outputStream.flush();
outputStream.close();
inputStream.close();
socket.close();
}catch (Throwable t){
t.printStackTrace();
}
// Garbage these references.
outputStream = null;
inputStream = null;
socket = null;
}
}
}
【０１３９】
添付書Ｂ９
この抜粋は、添付書Ｂの実施例の前／後に使用される例示的なアプリケーションのソースコードである。
import java.lang.*;
public class example{
/** Shared static field. */
public static example currentExample;
/** Shared instance field. */
public long timestamp;
/** Static intializer. (clinit) */
static{
currentExample = new example();
}
/** Instance intializer (init) */
public example(){
timestamp = System.currentTimeMillis();
}
}
【０１４０】
添付書Ｂ１０
ＩｎｉｔＬｏａｄｅｒ．ｊａｖａ
この抜粋は、ロードされているときにアプリケーションを修正するＩｎｉｔＬｏａｄｅｒのソースコードである。
import java.lang.*;
import java.io.*;
import java.net.*;
public class InitLoader extends URLClassLoader{
public InitLoader(URL[] urls){
super(urls);
}
protected Class findClass(String name)
throws ClassNotFoundException{
ClassFile cf = null;
try{
BufferedInputStream in = new 
BufferedInputStream(findResource(name.replace('.', 
'/').concat(“.class”)).openStream());
cf = new ClassFile(in);
}catch (Exception e){throw new ClassNotFoundException(e.toString());}
for (int i=0; i<cf.methods_count; i++){
// Find the <clinit> method_info struct.
String methodName = cf.constant_pool[
cf.methods[i].name_index].toString();
if (!methodName.equals(“<clinit>”)){
continue;
}
// Now find the Code_attribute for the <clinit> method.
for (int j=0; j<cf.methods[i].attributes_count; j++){
if (!(cf.methods[i].attributes[j] instanceof Code_attribute))
continue;
Code_attribute ca = (Code_attribute) cf.methods[i].attributes[j];
// First, shift the code[] down by 4 instructions.
byte[][] code2 = new byte[ca.code.length+4][];
System.arraycopy(ca.code, 0, code2, 4, ca.code.length);
ca.code = code2;
// Then enlarge the constant_pool by 7 items.
cp_info[] cpi = new cp_info[cf.constant_pool.length+7];
System.arraycopy(cf.constant_pool, 0, cpi, 0, 
cf.constant_pool.length);
cf.constant_pool = cpi;
cf.constant_pool_count += 7;
// Now add the constant pool items for these instructions, starting 
// with String.
CONSTANT_String_info csi = new CONSTANT_String_info(
((CONSTANT_Class_info)cf.constant_pool[cf.this_class]).name_index);
cf.constant_pool[cf.constant_pool.length-7] = csi;
// Now add the UTF for class.
CONSTANT_Utf8_info u1 = new CONSTANT_Utf8_info(“InitClient”);
cf.constant_pool[cf.constant_pool.length-6] = u1;
// Now add the CLASS for the previous UTF.
CONSTANT_Class_info c1 =
new CONSTANT_Class_info(cf.constant_pool.length-6);
cf.constant_pool[cf.constant_pool.length-5] = c1;
// Next add the first UTF for NameAndType.
u1 = new CONSTANT_Utf8_info(“isAlreadyLoaded”);
cf.constant_pool[cf.constant_pool.length-4] = u1;
// Next add the second UTF for NameAndType.
u1 = new CONSTANT_Utf8_info(“(Ljava/lang/String;)Z”);
cf.constant_pool[cf.constant_pool.length-3] = u1;
// Next add the NameAndType for the previous two UTFs.
CONSTANT_NameAndType_info n1 = new CONSTANT_NameAndType_info(
cf.constant_pool.length-4, cf.constant_pool.length-3);
cf.constant_pool[cf.constant_pool.length-2] = n1;
// Next add the Methodref for the previous CLASS and NameAndType.
CONSTANT_Methodref_info m1 = new CONSTANT_Methodref_info(
cf.constant_pool.length-5, cf.constant_pool.length-2);
cf.constant_pool[cf.constant_pool.length-1] = m1;
// Now with that done, add the instructions into the code, starting 
// with LDC.
ca.code[0] = new byte[3];
ca.code[0][0] = (byte) 19;
ca.code[0][1] = (byte) (((cf.constant_pool.length-7) >> 8) & 0xff);
ca.code[0][2] = (byte) ((cf.constant_pool.length-7) & 0xff);
// Now Add the INVOKESTATIC instruction.
ca.code[1] = new byte[3];
ca.code[1][0] = (byte) 184;
ca.code[1][1] = (byte) (((cf.constant_pool.length-1) >> 8) & 0xff);
ca.code[1][2] = (byte) ((cf.constant_pool.length-1) & 0xff);
// Next add the IFEQ instruction.
ca.code[2] = new byte[3];
ca.code[2][0] = (byte) 153;
ca.code[2][1] = (byte) ((4 >> 8) & 0xff);
ca.code[2][2] = (byte) (4 & 0xff);
// Finally, add the RETURN instruction.
ca.code[3] = new byte[1];
ca.code[3][0] = (byte) 177;
// Lastly, increment the CODE_LENGTH and ATTRIBUTE_LENGTH values.
ca.code_length += 10;
ca.attribute_length += 10;
}
}
try{
ByteArrayOutputStream out = new ByteArrayOutputStream();
cf.serialize(out);
byte[] b = out.toByteArray();
return defineClass(name, b, 0, b.length);
}catch (Exception e){
e.printStackTrace();
throw new ClassNotFoundException(name);
}
}
}
【図面の簡単な説明】
【０１４１】
【図１】従来のコンピュータの内部アーキテクチャを示す概略図である。
【図２】公知の対称型多重プロセッサの内部アーキテクチャを示す概略図である。
【図３】従来技術の分散コンピューティングを示す概略図である。
【図４】クラスタを使用した従来技術のネットワークコンピューティングを示す概略図である。
【図５】本発明の第１の実施形態に従って同じアプリケーションプログラムを実行する複数のマシーンを示す概略ブロック図である。
【図６】ＪＡＶＡコードを動作させ、これによってＪＡＶＡ仮想マシーンを構成するように配置された従来技術のコンピュータを示す概略図である。
【図７】図６に類似しているが、好ましい実施形態に従ってコードの初期ロードを示す図である。
【図８】図５に類似しているが、図７に示された方式でＪＡＶＡコードを各々が実行する複数のコンピュータの相互接続を示す図である。
【図９】ネットワーク内の各マシーンでの同じアプリケーションのロード中に行われる手順を示すフローチャートである。
【図１０】図９の手順に類似した修正された手順を示すフローチャートである。
【図１１】メモリ更新の第１の実施形態を利用して図８のマシーンで実行されるマルチスレッド処理を示す概略図である。
【図１２】図１１に類似した他の実施形態を示す概略図である。
【図１３】図８のコンピュータに対するマルチスレッドメモリ更新を示す図である。
【図１４】ＪＡＶＡコードで動作し、これによってＪＡＶＡ仮想マシーンを構成するように配置された従来技術のコンピュータを示す概略図である。
【図１５】アプリケーションプログラムを実行し、付加的なサーバーマシーンＸによってサービスされるｎ個のマシーンを示す概略図である。
【図１６】初期化ルーチンの修正を示すフローチャートである。
【図１７】初期化ルーチンの続行又は中断を示すフローチャートである。
【図１８】サーバーマシーンＸに送られる問合せを示すフローチャートである。
【図１９】図１８の要求に対するサーバーマシーンＸの応答を示すフローチャートである。
【図２０】＜ｃｌｉｎｉｔ＞命令に対する修正された初期化ルーチンを示すフローチャートである。
【図２１】＜ｉｎｉｔ＞命令に対する修正された初期化ルーチンを示すフローチャートである。
【図２２】複数のアプリケーションを同時に実行するために相互接続され、両方とも単一のコンピュータ上で実行されるアプリケーションを備えた２つのラップトップコンピュータを示す概略図である。
【図２３】図２２に類似した図であり、各コンピュータで実行される１つのアプリケーションを備えた図２２の装置を示す図である。
【図２４】図２２及び２３に類似した図であり、両方のコンピュータ上で同時に実行される両方のアプリケーションを備えた図２２の装置を示す図である。
【符号の説明】
【０１４２】
５０  アプリケーション
５３  ネットワーク
７１  ＤＲＴ
【図１】
2007534063.tif 000003
【図２】
2007534063.tif 000004
【図３】
2007534063.tif 000005
【図４】
2007534063.tif 000006
【図５】
2007534063.tif 000007
【図６】
2007534063.tif 000008
【図７】
2007534063.tif 000009
【図８】
2007534063.tif 000010
【図９】
2007534063.tif 000011
【図１０】
2007534063.tif 000012
【図１１】
2007534063.tif 000013
【図１２】
2007534063.tif 000014
【図１３】
2007534063.tif 000015
【図１４】
2007534063.tif 000016
【図１５】
2007534063.tif 000017
【図１６】
2007534063.tif 000018
【図１７】
2007534063.tif 000019
【図１８】
2007534063.tif 000020
【図１９】
2007534063.tif 000021
【図２０】
2007534063.tif 000022
【図２１】
2007534063.tif 000023
【図２２】
2007534063.tif 000024
【図２３】
2007534063.tif 000025
【図２４】
2007534063.tif 000026
【国際調査報告】
2007534063.tif 000027
2007534063.tif 000028
2007534063.tif 000029