JP2007534064A - 同期化を伴う多重コンピュータアーキテクチャ - Google Patents

同期化を伴う多重コンピュータアーキテクチャ Download PDF

Info

Publication number
JP2007534064A
JP2007534064A JP2007508675A JP2007508675A JP2007534064A JP 2007534064 A JP2007534064 A JP 2007534064A JP 2007508675 A JP2007508675 A JP 2007508675A JP 2007508675 A JP2007508675 A JP 2007508675A JP 2007534064 A JP2007534064 A JP 2007534064A
Authority
JP
Japan
Prior art keywords
computers
computer
index
int
lock
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
JP2007508675A
Other languages
English (en)
Inventor
ジョン マシュー ホルト
Original Assignee
ワラテック プロプライエタリー リミテッド
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Priority claimed from AU2004902146A external-priority patent/AU2004902146A0/en
Application filed by ワラテック プロプライエタリー リミテッド filed Critical ワラテック プロプライエタリー リミテッド
Publication of JP2007534064A publication Critical patent/JP2007534064A/ja
Pending legal-status Critical Current

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/52Program synchronisation; Mutual exclusion, e.g. by means of semaphores
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/30Arrangements for executing machine instructions, e.g. instruction decode
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F15/00Digital computers in general; Data processing equipment in general
    • G06F15/16Combinations of two or more digital computers each having at least an arithmetic unit, a program unit and a register, e.g. for a simultaneous processing of several programs

Landscapes

  • Engineering & Computer Science (AREA)
  • Theoretical Computer Science (AREA)
  • Software Systems (AREA)
  • Physics & Mathematics (AREA)
  • General Engineering & Computer Science (AREA)
  • General Physics & Mathematics (AREA)
  • Computer Hardware Design (AREA)
  • Multi Processors (AREA)
  • Stored Programmes (AREA)
  • Devices For Executing Special Programs (AREA)

Abstract

本発明は、アプリケーションプログラム(50)を複数のコンピュータ(M1、...Mn)上で同時に実行できるようにする修正されたコンピュータアーキテクチャ(50、71、72)を開示する。各コンピュータにある共有メモリは、全てのメモリ読み取り要求がローカルで満たされるように修正及び/又は上書きによって更新される。初期プログラムロード(75)又は類似のプログラムロード中、特定の資産(50A、50X−50Y)(同期)上でロックを取得(又は解放)するアプリケーションプログラムを生じる命令が識別される。全てのコンピュータが更新される修正同期ルーチンをもたらす追加命令が挿入される(162、163)。
【選択図】図8

Description

本発明は、コンピュータに関し、詳細には、通信ネットワークを介して相互接続された複数のコンピュータ上で同時にアプリケーションプログラムを動作することができる改良型マシーンアーキテクチャに関する。
コンピュータ及びコンピュータ関係の利用が出現して以来、コンピュータのソフトウェアは、単一のマシーン上で実行するように記述されてきた。図1に示されるように、当該従来技術の単一マシーン1は、バス4を介してメモリ3に接続された中央処理ユニット又はCPU2から構成される。また、モニタ5、キーボード6、及びマウス7のような単一マシーン1の種々の他の機能ユニットもバス4に接続されている。
マシーン1の性能に対する基本的制限は、CPU2によって操作されるデータ及びこれらの操作の結果をバス4によって移動する必要があることである。バス4は、バスへのアクセスを要望するユニットによって形成されるいわゆるバス「待ち行列」、コンテンション問題、及び同様のものを含む幾つかの問題の影響を受ける。これらの問題は、キャッシュメモリを含む種々の方策によってある程度までは軽減することができるが、このような方策は、マシーン1の管理オーバーヘッドを必然的に増大させる。
当然、何年もの間マシーン性能を向上させる種々の試みがなされてきた。1つの手法は、対称的マルチプロセッサを使用することである。この従来技術の手法は、いわゆる「スーパー」コンピュータで使用されており、図2に概略的に示されている。ここで複数のCPU12は、グローバルメモリ13に接続されている。同様に、ボトルネックは、CPU12とメモリ13との間の通信で発生する。このプロセスは、「シングルシステムイメージ」と呼ばれている。1つだけのアプリケーションと、グローバルメモリにわたり分散されるアプリケーション用のメモリの1つの全体コピーが存在する。単一のアプリケーションは、完全にトランスペアレントにいずれかのメモリロケーションとの間で読み込み及び書き込み(すなわち共有)を行うことができる。
ネットワークを介して相互接続された幾つかのこのようなマシーンが存在する場合には、これは、単一のマシーン用に記述された単一のアプリケーションを採用し、必要とされるメモリ資源を小部分に分割することによって達成される。次いで、これらの小部分は、幾つかのコンピュータにわたって分散され、全てのCPU12がアクセス可能なグローバルメモリ13を形成する。この手順は、単一の実行中のアプリケーションプログラムからメモリパーティションをマスキング又は隠すことに依存する。1つのマシーンの1つのCPUが、異なるマシーン内に物理的に位置付けられたメモリロケーションにアクセス(ネットワークを介して)する必要がある場合には、性能が低下する。
スーパーコンピュータは、高速の計算速度を達成する点においては技術的に成功しているが、これらが本質的に複雑であることによって、製造だけでなく管理に対しても極めて高価なものである点で商業的には成功していない。特に、シングルシステムイメージの概念は、「製品」である(すなわち大量生産された)コンピュータ及びネットワークを越えて拡張することは決してできない。特に、シングルシステムイメージの概念は、超高速(及び従って極めて高価)ネットワークによって相互接続された超高速(及び同様に極めて高価)コンピュータ上でのみ実用的なアプリケーションが見られた。
複数のマシーンを使用することで増大されたコンピュータパワーの別の可能性は、図3に概略的に示されている分散コンピューティングの従来技術の概念から生じる。この公知の構成では、単一のアプリケーションプログラム(Ap)は、その作成者(又はアプリケーションプログラムについてよく理解している別のプログラマー)によって種々の離散的タスクに区分され、例えば図3のケースnが整数3である3つのマシーン上で実行できるようにする。ここでの目的は、マシーンM1...M3の各々がアプリケーション全体のうちで異なる1/3を実行することであり、更に、種々のマシーンに加えられる負荷をほぼ等しくすることである。マシーンは、通信リンク、インターネット、イントラネット、ローカルエリアネットワーク、及び同様のものなどの種々の形式で提供することができるネットワーク14を介して通信する。通常、このようなネットワーク14のオペレーションの速度は、個々のマシーンM1、M2、その他の各々におけるバス4のオペレーション速度よりもかなり遅い。
分散コンピューティングには幾つかの欠点がある。第1に、アプリケーションを分割するジョブは困難であり、これはマニュアルで行わなければならない。第2に、ネットワーク14を介したデータ、部分的な結果、結果、及び同様のものの通信は、管理上のオーバーヘッドである。第3に、分割が必要であることにより、例えば3つに分割されたアプリケーションが4つのマシーン上ではうまく動作しないので、より多くのマシーンを用いることによって機能を高めることが極めて困難になる。第4に、マシーンの1つを無効にする必要がある場合、システム全体の性能がかなり低下する。
別の従来技術の構成は、図4に概略的に示された「クラスタ」を介したネットワークコンピューティングとして公知である。この方法では、アプリケーション全体がマシーンM1、M2...Mnの各々にロードされる。各マシーンは、共通のデータベースと通信するが、他のマシーンとは直接通信しない。各マシーンは同じアプリケーションを実行するが、異なる「ジョブ」を実行しており、固有のメモリだけを使用する。これは、その各々が列車のチケットを一般の人に販売する幾つかの窓口に幾分類似している。この方法は機能を実行し、拡張可能であるが、大抵はネットワークを管理するのが難しいといった欠点がある。
JAVA及びMICTPSOFT.NETなどのコンピュータ言語には、プログラマーが扱う構成体の2つの主要なタイプがある。JAVA言語では、これらはオブジェクト及びクラスとして知られる。あらゆるコンピュータ環境において、このような資産、資源、又は構造を利用することでアプリケーションプログラムの一部が同時に同じ資源を用いようとするのを防ぐことを可能にするロックを取得及び解放することが必要である。JAVA環境では、これは同期として知られる。これは、JAVAでは「montor enter」及び「monitor exit」命令又はルーチンにより実現される。他の言語は異なる項を使用するが、類似の概念を利用する。
本発明は、アプリケーションプログラムが複数のコンピュータ上で同時に動作するコンピューティング環境を開示する。このような環境では、「montor enter」及び「monitor exit」がマシーンの全てにわたって矛盾のない方式で確実に動作することが必要である。これが本発明の起源である矛盾のない資源ロックの目標である。
本発明の第1の態様によれば、単一のコンピュータでのみ動作するように各々記述されているが、通信ネットワークによって相互接続された複数のコンピュータ上で同時に実行する少なくとも1つのアプリケーションプログラムを有する多重コンピュータシステムであって、アプリケーションプログラムの異なる部分がコンピュータのうちの異なるコンピュータ上でほぼ同時に実行され、各部分において、同様の複数の実質的に同一のオブジェクトが対応するコンピュータに各々作成され、各々が実質的に同一の名前を有し、本システムは、コンピュータの全てに利用可能なロック手段を含み、コンピュータ内の名前を付けられたオブジェクトを利用したいと望んでいるあらゆるコンピュータが、ロック手段から許可ロックを取得し、許可ロックにより利用が許可され、許可ロックが放棄されるまで他のコンピュータ全てがこれらの対応する名前を付けられたオブジェクトを利用するのが阻止されることを特徴とする多重コンピュータシステムが開示される。
本発明の第2の態様によれば、通信リンクを介して相互接続され、単一のコンピュータでのみ動作するように各々記述されている少なくとも1つのアプリケーションプログラムを同時に実行する複数のコンピュータであって、各コンピュータがアプリケーションプログラムの異なる部分をほぼ同時に実行し、アプリケーションプログラム部分を動作中の各コンピュータは、各コンピュータに物理的に位置付けられたローカルメモリ内にあるオブジェクトだけを利用し、各コンピュータによって利用されるローカルメモリのコンテンツは、基本的に類似しているが、各瞬間では同一でなく、コンピュータの全てのコンピュータが、1つのコンピュータだけによるローカルオブジェクトの利用を許可するロック取得ルーチン及びロック解放ルーチンを有し、複数のコンピュータの残りの各々は、これらの対応するオブジェクトの利用からロックアウトされることを特徴とする複数のコンピュータが開示される。
本発明の第3の態様によれば、単一のコンピュータでのみ動作するように各々記述されている少なくとも1つのアプリケーションプログラムを複数のコンピュータ上で同時に実行する方法であって、前記コンピュータは、通信ネットワークによって相互接続されており、本方法が、(i)コンピュータのうちの異なるコンピュータ上でアプリケーションプログラムの異なる部分を実行し、各部分について対応するコンピュータ内に同様の複数の実質的に同一のオブジェクトを各々作成し、各々に実質的に同一の名前を持たせる段階と、(ii)コンピュータ内の名前を付けられたオブジェクトを利用することを意図するコンピュータのいずれにも、利用を許可し、許可ロックが放棄されるまで他のコンピュータの全てがこれらの対応する名前を付けられたオブジェクトの利用を阻止する許可ロックを取得するように要求する段階と、を含む方法が開示される。
本発明の第4の態様によれば、単一のコンピュータでのみ動作するように記述されているが、通信ネットワークを介して相互接続された複数のコンピュータの異なるコンピュータ上でその異なる部分が各々ほぼ同時に実行されることになるアプリケーションプログラムの矛盾のない同期を保証する方法であって、本方法が、(i)ロード時、又はロード前、又はロード後にアプリケーションプログラムを精査して、同期ルーチンを定義する各プログラム段階を検出する段階と、(ii)同期ルーチンを修正して1つだけのコンピュータによるオブジェクトの利用を保証し、残りのコンピュータ全てがこれらの対応するオブジェクトを同時に利用することを阻止する段階と、を含む方法が開示される。
本発明の第5の態様によれば、単一のコンピュータ上でのみ動作するように記述された単一のアプリケーションプログラムの個々のスレッドが、通信リンクを介して相互接続された複数のコンピュータのうちの対応するコンピュータ上で各々同時に処理されるマルチスレッド処理コンピュータオペレーションにおいて、各スレッドを処理するコンピュータに物理的に関連付けられたローカルメモリ内のオブジェクトは、他の各コンピュータのローカルメモリ内に対応するオブジェクトを有し、コンピュータの1つだけがオブジェクトを利用することを許可する段階と、残りのコンピュータの全てがこれらの対応するオブジェクトを同時に利用するのを阻止する段階とを含む改良が開示される。
本発明の第6の態様によれば、記憶媒体内に記憶され、上述の方法の実行を複数のコンピュータに許可するように動作可能なプログラム命令のセットを含むコンピュータプログラム製品が開示される。
本発明の実施形態を図面を参照しながら説明する。
本明細書は、説明された実施形態の種々の態様を実装する実際のプログラムフラグメントを提供する添付書A及びDを含む。添付書Aはフィールドに関し、添付書Dは同期化に関する。
図5に関連して、本発明の好ましい実施形態によれば、単一のアプリケーションプログラム50は、ネットワーク53を介して通信する幾つかのマシーンM1、M2...Mn上で同時に動作することができる。以下に明らかになるように、マシーンM1、M2...Mnの各々は、各マシーンM1、M2...Mn上で同じアプリケーションプログラム50で動作し、従って、マシーンM1、M2...Mnの全ては、同じアプリケーションコード及びデータ50を有する。同様に、マシーンM1、M2...Mnの各々は、各マシーンM1、M2...Mn上の同じ(又は実質的に同じ)モディファイアー(modifier,変更子)51で動作し、従って、マシーンM1、M2...Mnの全ては、51/2で示されるマシーンM2のモディファイアーと同じ(又は実質的に同じ)モディファイアー51を有する。更に、各マシーンM1、M2...Mn上でのアプリケーション50のロード中、又は実行前に、各アプリケーション50は、同じ規則(又は僅かな最適化変更が各モディファイアー51/1...51/nで許可されているので、実質的に同じ規則)に従って対応するモディファイアー51で修正されている。
上述の構成の結果として、マシーンM1、M2...Mnの各々が、例えば10MBの共有メモリ容量を有する場合には、各アプリケーション50が利用可能な合計共有メモリは、予想されるように10nMBではなくむしろ10MBだけである。しかしながら、これによって改良されたオペレーションがどのように生じるかは、以下で明らかになるであろう。当然、各マシーンM1、M2...Mnは、非共有メモリ容量を有する。マシーンM1、M2...Mnの非共有メモリ容量は、通常ほぼ等しいが、必須ではない。
図6に概略的に示されるように仮想マシーンを作成することによって、アプリケーションの特定の言語でマシーン(種々の製造業者の1つによって生産され、種々の異なる言語の1つで動作するオペレーティングシステムを有する)を動作させることは従来技術から公知である。図6の従来技術の構成は、Java言語で記述されJava仮想マシーン61内で実行するアプリケーション50の形式を取る。従って、アプリケーションの目的とする言語がJAVA言語である場合、マシーン製造業者及びマシーンの内部の詳細に関わらず、JAVAコードを操作できるJAVA仮想マシーンが作成される。更なる詳細については、米国のSun Microsystems Inc.のT.Lindholm及びF.Yellinによる「The JAVA Virtual Machine Specification” 2nd Edition(JAVA仮想マシーン仕様)」第2版を参照されたい。
図6のこの公知の従来技術の構成は、図7に見られるように「分散ランタイム」又はDRT71と便宜上呼ばれる付加的な機能を提供することによって、本発明の好ましい実施形態に従って修正される。図7では、アプリケーション50は、矢印75によって示されるロード手順で分散ランタイムシステム71を介してJava仮想マシーン72にロードされる。分散ランタイムシステムは、分散コンピューティング環境(DCE)の名称でOpen Software Foundationから利用可能である。特に、分散ランタイム71は、最初にJAVA仮想マシーン72を作成するように、JAVAアプリケーション50の矢印75によって示されるロード手順中に作動し始める。ロード中のオペレーションのシーケンスは、図9に関して以下に説明する。
図8は、各々が図7に示されるようにJAVA仮想マシーンを用いる図5の構成の修正された形式を示す。同様に同じアプリケーション50が各マシーンM1、M2...Mnにロードされることは明らかであろう。しかしながら、矢印83によって示されているがマシーンハードウェアからは物理的に経路指定されている各マシーンM1、M2...Mn間の通信は、各マシーン内の個々のDRT71/1...71/nによって制御される。従って、実際にはこれは、マシーンM1、M2...Mn自体ではなくネットワーク73を介して互いに通信しているDRT71/1...71/nとして概念化することができる。
ここで図7及び9を参照すると、ローディング手順75の間、各JAVA仮想マシーン72を作成するためにロードされているプログラム50が修正される。この修正は図9の90で開始し、ロードされているアプリケーション50において全メモリロケーション(JAVAではフィールドと呼ばれるが、他の言語でも同等の用語が使用される)を検出する初期ステップ91を包含する。このようなメモリロケーションは、ステップ92及び93での連続した処理において識別される必要がある。ローディング手順75中のDRT71は、メモリロケーション全てのリストを作成し、このようにしてオブジェクト及びクラスによってリストされるJAVAフィールドを識別する。揮発性フィールド及び同期フィールドの両方がリストされる。
修正手順の次のステップ(図9の92で示される)は、全処理動作を特定するために実行可能なアプリケーションコードをサーチすることであり、該全処理動作では、ステップ91で作成されたリストに対応するフィールド値を操作又は変更し、これによって対応するメモリロケーションでの値が変更されるようにフィールドに書き込む。フィールド値を変更するこのようなオペレーション(通常、JAVA言語におけるputstatic又はputfield)が検出された場合、フィールドの値が変わったことを全ての他のマシーンに確実に通知されるように、ステップ93で「更新伝播ルーチン(updating propagating routine)」がプログラムのこの場所に挿入される。その後、ロード手順は、図9のステップ94によって示される通常の方法で続行される。
ロード中の初期修正の他の形式が図10に示されている。ここで開始及びリスティングステップ90及び91並びにサーチステップ92は、図9と同じである。しかしながら、処理スレッドが更新を実行するステップ93で「更新伝播ルーチン」を挿入するのではなく、「警報ルーチン(alert routine)」がステップ103で挿入される。「警報ルーチン」は、処理に使用されずDRTに割り当てられる1つ又は複数のスレッドに対し必要な伝播を実行するよう指示を与える。このステップ103は、より低いオーバーヘッドを生じる簡単な代替手段である。
ロード手順中にこの初期修正が行われると、次いで、図11及び12に示されるマルチスレッド処理オペレーションのいずれか1つが行われる。図11で分かるように、スレッド111/1...111/4からなるマシーン上のマルチスレッド処理110が行われ、第2スレッド111/2の処理(この実施例での)では、スレッド111/2がフィールド値の変更をステップ113で認識することになる。このステップで、スレッド111/2の通常の処理はステップ114で停止し、同じスレッド111/2は、ステップ113で行われた変更フィールドのアイデンティティ及び変更値をネットワーク53を介して全ての他のマシーンM2...Mnに通知する。次いでステップ115で、当該通信手順の最後において、スレッド111/2は、フィールド値の変更がある次のインスタンスまで処理を再開する。
図12に示された他の構成では、ステップ113でスレッド121/2がフィールド値の変更を認識すると、スレッド121/2は、DRT処理120に割り当てられた別のスレッド121/1がステップ128によりネットワーク53を介しステップ113で検出された変更フィールドのアイデンティティ及び変更値を全ての他のマシーンM2...Mnに伝播するようにDRT処理120(ステップ125及び矢印127によって示されるように)に指示する。これは、迅速に実行できるオペレーションであり、すなわち、スレッド111/2がステップ115で処理を再開する前に、該初期スレッド111/2の処理は、ステップ125で示されるように瞬間的に中断される。次いで、変更(矢印127によって示されるような)を通知された他のスレッド121/1は、その変更をステップ128で示されるようにネットワーク53を介して他のマシーンM2...Mnの各々に伝達する。
図12のこの第2の構成は、種々のスレッド111/1...111/3及び121/1(これらは一般に均等要求の影響を受けない)の処理能力をうまく利用し、増大する「n」のサイズと共に良好な拡張を与える(nは2以上の整数であって、ネットワーク53に接続されアプリケーションプログラム50を同時に実行するマシーンの総数を表す)。どの構成が使用されるかに関わらず、ステップ113で検出された変更フィールド及びアイデンティティ及び値は、ネットワーク上の他のマシーンM2...Mn全てに伝播される。
これは図13に示され、DRT71/1及び図12のスレッド121/1(図13のステップ128によって表わされる)は、マシーンM1での処理によってネットワーク53を介して図12のステップ113で作成されたリストされたメモリロケーションのアイデンティティ及び変更値を他のマシーンM2...Mnの各々に送信する。
他のマシーンM2...Mnの各々は、ネットワーク53からアイデンティティと値のペアを受信し且つ新しい値をローカルの対応するメモリロケーションに書き込むことにより、マシーンMnのための図13のステップ135及び136によって示された動作を実行する。
分散型ソフトウェアを利用する図3の従来技術の構成では、1つのマシーンのソフトウェアから別のマシーンに物理的に位置付けられたメモリへのメモリアクセスは、マシーンを相互接続するネットワークによって許可される。しかしながら、このようなメモリアクセスは、マシーンの中央処理ユニットの106−107サイクルのオーダーの処理に遅延を生じる可能性がある。これは大部分が、複数の相互接続されたマシーンの性能の低下に起因する。
しかしながら、図8に関して上述された本構成では、全フィールドの現在の値は、メモリの読み取り要求を生成する処理を実行しているマシーン上に記憶されるので、データの全読み取りがローカルで達成されることを理解されたい。このようなローカル処理は、中央処理ユニットの102−103サイクル内で達成することができる。従って、実際には読み取りを伴うメモリアクセスを実質的には待機することはない。
しかしながら、ほとんどのアプリケーションソフトウェアは、メモリを頻繁に読み取るが、書き込みは比較的まれにしか行わない。この結果、メモリの書き込み又は再書き込みの速度は、メモリの読み取り速度に比べて比較的遅い。メモリの書き込み又は再書き込みに対するこの低速の要求に起因して、フィールドは、低価格製品ネットワーク53を介した比較的低速で頻繁に更新することができ、更にこの低速では、メモリへ書き込むためのアプリケーションプログラムの要求を満たすのに十分である。この結果、図8の構成の性能は、図3の構成よりも極めて優れていることになる。
上記に関連した別の修正形態において、変更フィールドのアイデンティティ及び値をバッチにグループ分けし、種々のマシーンを相互接続するネットワーク53の通信速度に対する要求を更に低減することができる。
フィールドを最初に記録する際に各DRT71によって作成されたテーブルでは、各フィールドに対してネットワーク全体で共通であり且つネットワークが認識する名前又はアイデンティティが存在することは当業者には明らかであろう。しかしながら、個々のマシーンでは、各マシーンが固有の内部プロセスに従って異なるロケーションで変更フィールド値を漸次記憶するので、所与の名前付きフィールドに対応するメモリロケーションは時間と共に変わることになる。従って、DRTの各々におけるテーブルは、一般には異なるメモリロケーションを有するが、各グローバル「フィールド名」は、異なるメモリロケーション内に記憶された同じ「フィールド値」を有することになる。
ロード中のアプリケーションプログラムの上述の修正は、以下の最大5つの方法で達成可能であることが当業者には明らかであろう。
(i)ロード時の再コンパイル
(ii)プリコンパイルによるロード前の処理
(iii)ロード前のコンパイル
(iv)「実行時」(JIT)コンパイル、
(v)ロード後の再コンパイル(しかしながら、又は例えば、分散環境での関連した又は対応するアプリケーションコードを実行する前)
従来、用語「コンパイル」とは、例えばソースからオブジェクトコード、又は1つの言語から別の言語へのコード又は言語における変更を意味する。明確には、本明細書において用語「コンパイル」(及びその文法的に等価なもの)の使用は同じコード又は言語内に限定されず、修正形態を含む又は包含することができる。
第1の実施形態において、特定のマシーン、例えばマシーンM2は、それ自体にアプリケーションコードをロードし、これを修正し、次いで他のマシーンM1、M3...Mnの各々に(順次又は同時に)修正コードをロードする。「マスタ/スレーブ」と呼ぶ場合があるこの構成では、マシーンM1、M3、...Mnの各々が、マシーンM2によって与えられるものをロードする。
更に別の実施形態において、各マシーンはアプリケーションコードを受け取るが、これを修正し、修正コードをそのマシーンにロードする。これによって、各マシーンが行う修正をそのアーキテクチャ及びオペレーティングシステムに基づき僅かに異なるように最適化することができ、更に全ての他の類似の修正と整合を取ることができる。
別の構成では、特定のマシーン、例えばM1は修正されていないコードをロードし、全ての他のマシーンM2、M3...Mnは、オリジナルのアプリケーションコードを削除し修正されたバージョンをロードするよう修正を行う。
全ての事例において、供給は、ブランチ(すなわち、M2がM1、M3、M4などの各々に直接提供する)又はカスケード或いはシーケンシャル(すなわち、M2はM1に供給し、次にM1がM3に供給し、次いで、M3がM4に供給する、以下同じ)とすることができる。
更に別の構成では、M1からMnまでのマシーンは追加のマシーン(図示せず)に全てのロード要求を送ることができ、該追加マシーンは、アプリケーションプログラムを実行しておらず、前述の方法のいずれかを介して修正を行い、修正ルーチンをマシーンM1からMnまでの各々に返し、次いで、マシーンM1からMnがこの修正ルーチンをローカルにロードする。この構成では、マシーンM1からMnは、修正ルーチンを各マシーンに返すこの追加のマシーンに全ロード要求を転送する。この追加のマシーンによって行われる修正は、本発明の範囲内で保護される修正形態の全てを含むことができる。
コンピュータ関連技術に熟練した人であれば、コンピュータコードで修正を作製する際に使用される少なくとも4つの技術を認識することになる。第1は、オリジナル(ソース)言語で修正を行うことである。第2は、オリジナルコード(例えばJAVAでの)を中間表現(又は中間言語)に変換することである。この変換を行うと、修正がなされ、次いで逆変換される。これは、修正されたJAVAコードの要求結果をもたらす。
第3の可能性は、マシーンコードに(直接又は前述の中間言語を介して)変換することである。次にマシーンコードは修正された後、ロードされ実行される。第4の可能性は、オリジナルコードを中間表現に変換することであり、この中間表現は次に修正され、その後マシーンコードに変換される。
本発明は、全ての4つの修正ルートと、更にこのようなルートの2つ、3つ、又は4つ全部の組み合わせを包含する。
ここで図14を参照すると、JAVA仮想マシーンとして動作する単一の従来技術のコンピュータの概略図が示されている。このように、マシーン(種々の製造業者のいずれか1つによって生産され、種々の異なる言語のいずれか1つで動作するオペレーティングシステムを有する)は、アプリケーションプログラム50の特定の言語、この場合はJAVA言語で動作することができる。すなわち、JAVA仮想マシーン72は、JAVA言語でコード50を動作させることができ、マシーン製造業者及びマシーンの内部詳細に関係なくJAVAアーキテクチャを利用することができる。
更に、図14の単一のマシーンは、プログラマーが同期ルーチンを利用することで指定されたときに特定のオブジェクト50X−50Zの同期を容易に行うことができる。各オブジェクトはローカルにだけ存在するので、該オブジェクトが図14の単一のJAVA仮想マシーンはプログラマーによって指定された通りに適切に同期され、従って任意の単一時点で実行可能コードの一部で利用されるのを保証することができる。実行可能コードの別の部分が同じオブジェクトを使用することを望む場合には、可能性のあるコンテンションがJAVA仮想マシーン72により解消され、アプリケーションプログラムの他の実行中の部分は、先の部分が終了するまで待機するようにされる。
同じ手順は、クラス50Aに対して準用される。特に、JAVA言語及びアーキテクチャを使用してプログラムを記述するコンピュータプログラマーは、この競合を回避するために同期ルーチンを使用するだけでよい。従って、単一のJAVA仮想マシーンは、クラス及びオブジェクトの利用度を把握し、目立たない方式で必要に応じてあらゆる対応する問題を防ぐことができる。1つだけのオブジェクト又はクラスが排他的に使用されるプロセスが「同期」と呼ばれる。JAVA言語において、命令「monitorenter」及び「monitorexit」は、同期ルーチンの開始と終了を表し、資産が競合の対象とならないようにする「ロック」の取得と解放をそれぞれもたらす。
しかしながら、図8(及び図20−22)に示される構成では、複数の個々のコンピュータ又はマシーンM1、M2....Mnが備えられ、その各々は通信ネットワーク53を介して相互接続されており、その各々はモディファイアー51(図5に示され、図8のDRT71によって実現される)を備え、共通アプリケーションプログラム50がロードされる。本質的に、モディファイアー51又はDRT71は、マシーンの1つで実行されるアプリケーションプログラム50の一部が、オブジェクト50X−50Z又はクラス50Aなどの特定のローカル資産を排他的に(例えば同期によって)利用する場合に、他のマシーンM2...Mnがそのローカルメモリ内の対応する資産を利用しないことを保証する。
特に、1つの特定のマシーン(例えば、M3)は、あるオブジェクト又はクラスを排他的に使用し、別のマシーン(例えば、M5)はまた、そのオブジェクト又はクラスを同時に排他的に使用するようコードによって指示することができる。従って、オブジェクト又はクラスが両方のマシーンによって排他的に使用される場合には、全体的にオブジェクト及びアプリケーションの動作は定義されず、すなわち、プログラマーによって明確に指定されたオブジェクトの適切な排他的使用がない場合、マシーンM5とマシーンM3との間の恒久的な矛盾が起こる可能性が高い。従って、同じアプリケーションプログラムの同時オペレーションに必要とされるマシーンM1、M2...Mnの各々についての実質的に同一のメモリコンテンツの目標は達成されないことになる。
矛盾のない同期を保証するために、アプリケーションプログラムは、同期ルーチンを定義するプログラムステップを検出するために精査される。この精査は、ロード前、又はロード手順中のいずれか、或いはロード手順後(且つアプリケーションコードの関連の対応する部分の実行前)でも行うことができる。用語「コンパイル」が通常は、コード又は言語における変更、例えばソースからオブジェクトコード、或いは1つの言語から別の言語への変更を伴うことを理解した上で、これはコンパイル手順に形容することができる。しかしながら、本実施例では、用語「コンパイル」(及び、その文法的に等価なもの)は、同じコード又は言語内に限定されず、同じコード又は言語内の修正を含み包含することができる。
付随の添付書Dを参照する。添付書D1は、未修正の同期ルーチンからの一般的コードフラグメントであり、添付書D2は、修正された同期ルーチンに関する等価物である。
添付書D1及びD2はそれぞれ、同期ルーチンの前及び後の抜粋である。本方法に追加される修正コードは、下線で強調されている。添付書D1のオリジナルコードサンプルでは、コードは、同期命令文内の共有メモリロケーション(カウンタ)をインクリメントする。同期命令文の目的は、マルチスレッドアプリケーションにおけるインクリメントオペレーションのスレッドの安全性を保証することである。従って、分散型環境での同期を管理することなく、各マシーンが分離して同期を行い、よって場合によっては同時に共有カウンタをインクリメントし、潜在的な競合条件(又は複数の競合条件)及び矛盾したメモリを生じることになる。明らかに、これはアプリケーションプログラムのプログラマーが発生を予想したものではない。
そこで、DRTを利用することで、アプリケーションコードは、同期ルーチンを変更することによってマシーンにロードされるときに修正される。行われた変更(下線で強調されている)は、同期ルーチンが実行する初期命令及び終了命令である。これらの追加された命令は、分散型環境で全ての他のマシーンにわたって追加して同期を行うように機能し、これによって複数のマシーン全体でアプリケーションプログラムの同期動作を保全する。
DRTのacquireLock()法は、このオブジェクトの一意の識別子を表わす引数(添付書D2を参照のこと)、例えばオブジェクトの名前、当該オブジェクトへの参照、又は全ノードにわたってこのオブジェクトを表わす固有の数字を取り、指定されたオブジェクトのグローバルロックを取得するのに使用される。このように、DRTは、複数のオブジェクトのどれが既に同期されており、どれが同期されていないかに関して混同することなく、各オブジェクトの一意の識別子を使用して共有同期テーブルの正確な記録に照会することにより同時に複数のオブジェクトの同期をサポートすることができる。
DRTは、幾つかの方法でオブジェクトの同期状態を判定することができる。DRTは、このオブジェクトのローカルコピーが現在同期されているかどうかを各マシーンに尋ね、いずれかのマシーンが真を返信した場合には、当該オブジェクトが同期されなくなるまで待機し、そうでなければこのオブジェクトをローカルで同期する。或いは、ローカルマシーン上のDRTは、共有記録テーブル(場合によっては別個のマシーン(例えばマシーンX)上、或いはローカルマシーン上の矛盾のない共有記録テーブル、又はデータベース)に照会して、このオブジェクトがいずれかの他のマシーンによって同期にマークされているかどうかを判定し、同期にマークされている場合、オブジェクトの状態が「非同期」に変更されるまで待機し、次いで、オブジェクトを同期としてマークすることでロックを取得し、同期にマークされていない場合には、このマシーンによって同期されたものとしてオブジェクトにマークを付けることによってロックを取得する。
DRTが、このオブジェクトに対するロックを現在他のマシーンが有していない(すなわち、このオブジェクトを同期している他のマシーンはない)と判定した場合、例えば同期状態の共有テーブルにおける対応する入口を修正すること、或いは現在のマシーンに加えて全ての他のマシーン上でロックを順次取得することによって、全ての他のマシーン上でこのオブジェクトに対するロックを取得する。このオブジェクトを現在同期している他のマシーンが存在しないことをこのマシーンが正常に確認し、これに応じてこのマシーンがローカルに同期したときにのみ、オリジナル同期コードブロックの実行を開始することができる。
他方、別のマシーンがこのオブジェクトを既に同期していることをDRTが判定すると、このマシーンは、このオブジェクトに対する同期命令文を現在実行している他のマシーンがないこと、及びこのマシーンがこれに応じてローカルでオブジェクトを同期したことをDRTが確認できるようになるまでオリジナルコードブロックの実行を延期することになる。このような場合、オリジナルコードブロックは、同期された命令文の並行実行により生じる競合条件、メモリの不整合性、及びその他に起因して、関与するマシーン全体でオブジェクトを損傷させる場合があるので、このオブジェクトに対する同期命令文を実行している他のマシーンがないことをこのマシーンが保証できるまで実行されることになるNOTである。従って、このオブジェクトが現在「同期されている」とDRTが判定した場合、DRTは、対応する「releaseLock()」オペレーションがロックの現在の所有者によって実行されるようになるまで、「acquireLock()」オペレーションの実行を停止することによってオリジナルコードブロックの実行を阻止する。
従って、「releaseLock()」オペレーションの実行時に、現在ロックを「所有」している(すなわち、同期命令文を実行している)マシーンは、例えば、同期状態の共有テーブルで「非同期」としてこのオブジェクトをマークすることによって、或いは全ての他のマシーンで取得されたロックを順次解放することによって、その同期命令文のクローズを指示する。この時点で、対応する同期命令文の実行開始を待機しているあらゆる他のマシーンは、例えば同期状態の共有テーブルにおいてこのオブジェクトに対する同期命令文を実行するものとして自己マークすること、或いは他のマシーンの各々でローカルロックを順次取得することなど、延期された(すなわち遅延された)「acquireLock()」オペレーションの実行を再開することによって、このオブジェクトのロックの所有権を請求することができる。
そこで、DRTを利用して、アプリケーションコードは、同期ルーチン(開始(monitorenter)及び終了「monitorexit」命令(又は複数の命令)からなる)を変更することでマシーンにロードされるときに修正される。行われる変更(下線で強調されている)は、同期ルーチンが実行する初期命令である。これらの追加される命令は、このロックが別のマシーンによって既に取得されているかどうかをチェックする。このロックが別のマシーンによって取得されていない場合、このマシーンのDRTは、このマシーンがロックを取得したことを全ての他のマシーンに通知し、これによって他のマシーンがこのロックに対して同期ルーチンを実行するのを中止させる。
DRTは、多くの方法でマシーンのロック状態を記録することができる。例えば、
1.同期ルーチンへの入口に応じて、DRTは各マシーンに個々に照会し、このロックが既に取得されているかどうかを確かめる。取得されている場合、DRTは、全ての他のマシーンがこの資産又はオブジェクトのロックをもはや所有しなくなるまで同期ルーチンの実行を停止する。取得されていない場合、DRTは、この同期ルーチンを実行する。
或いは、
2.同期ルーチンへの入口に応じて、DRTは、いずれかのマシーンが現在このロックを「所有」しているかどうかを示す記録の共有テーブル(例えば、共有データベース、又はしているマシーンの各々の共有テーブルのコピー)に照会する。所有している場合、DRTは、全ての他のマシーンがこのオブジェクトのロックをもはや所有しなくなるまでこのマシーンでの同期ルーチンの実行を停止する。所有していない場合、DRTは、このロックの所有者として共有テーブル(又は、例えば複数のマシーンに複数の記録のテーブルがある場合には複数のテーブル)にこのマシーンを記録し、次いで同期ルーチンを実行する。
同様に、ロックが解放され、すなわち同期ルーチンの実行が終了すると、DRTは、多くの他の方法でマシーンのロック状態を「未記録」にすることができる。例えば、
1.同期ルーチンへの出口に応じて、DRTは、もはやロックを所有していないことを互いのマシーンに個々に通知する。
或いは、
2.同期ルーチンへの出口に応じて、DRTは、このマシーンがこのロックを所有しているものとして記録されないように記録の共有テーブルにおいてこのロックされた資産又はオブジェクトについての記録を更新する。
また更に、DRTは、複数の他の方法でロックされたオブジェクトを取得することを要求しているマシーンを待ち行列に入れることができる。
例えば、
1.同期ルーチンへの入口に応じて、DRTは、特定のマシーンが現在所有しているマシーンによる解放時にロックの取得を望んでいることをロックされたオブジェクトの現在の所有者に通知する。他に待機しているマシーンがない場合、指定されたマシーンは、指定されたマシーンの関心のある記録をテーブル内に記憶し、ロックされたオブジェクトの同期ルーチンの出口に従って、次いでこのロックされたオブジェクトを取得できる待機中のマシーンに通知し、よってその同期ルーチンの実行を開始する。
2.同期ルーチンへの入口に応じて、DRTは、特定のマシーン(例えば、マシーンM6)がそのマシーン(例えば、マシーンM4)による解放時にロックの取得を望んでいることをロックされたオブジェクトの現在の所有者に通知する。そのマシーンM4が、このロックされたオブジェクトについて待機中のマシーンのその記録を照会した後で見つけられた場合、1つ又はそれ以上の待機しているマシーンが既にあることを見つけ、次いでこのロックされたオブジェクトを取得しようとしているマシーンのリストの最後にマシーンM6を追加するか、或いはM6からの要求を、最初の待機中のマシーン、又はいずれかの他の待機中のマシーンに転送し、その後、記録のこれらのテーブル内にマシーンM6を記録する。
3.同期ルーチンへの入口に応じて、DRTは、記録の共有テーブル(例えば、全てのマシーンがアクセス可能な共有データベースに記憶されたテーブル、又は実質的に類似の複数の別個のテーブル)に自己記録する。
また更に、DRTは、以下の他の方法でこのマシーンによる同期ルーチンの出口に応じてこのロックを取得するよう待ち行列に並んだ他のマシーンに通知できる。例えば、
1.同期ルーチンの出口に対応して、DRTは、ロックが解放されることを待機しているマシーンの1つ(例えば、待機中のマシーンの待ち行列内のこの第1のマシーン)に通知する。
2.同期ルーチンの出口に対応して、DRTは、ロックが解放されたことを待機しているマシーンの1つ(例えば、待機中のマシーンの待ち行列の第1マシーン)に通知し、更に、マシーン(例えば、このロックを待機している第2マシーン及び次のマシーン)の全待ち行列のコピーを供給する。このようにして、第2マシーンは、第1マシーンから待機中のマシーンのリストを引き継ぎ、これによってリストの下にある各マシーンがロックを取得した後解放するように待機中のマシーンの待ち行列の連続性を保証する。
上述の精査の間、「monitorenter」及び「monitorexit」命令(又は方法)は、最初に探され、見つけられた場合、修正コードが挿入されて、修正された同期ルーチンをもたらす。この修正ルーチンは、ロックを取得し解放する。この修正及びロードを実行できる幾つかの異なるモードが存在する。
図15で分かるように、図8の一般的構成に対する修正は、マシーンM1、M2...Mnがこれまでと同じであり、全マシーンで同じアプリケーションプログラム50を同時に実行するようにされる。しかしながら、以前の構成は、ハウスキーピング機能、例えば、特に構造、資産、及び資源の同期を好都合に供給できるサーバーマシーンXを備えることによって修正される。このようなサーバーマシーンXは、その計算負荷が低いため、PCなどの低価格製品コンピュータとすることができる。図15の破線で示されるように、2つのサーバーマシーンX及びX+1は、システムの全体的な信頼性を高める冗長性の目的で設けられる。2つのこのようなサーバーマシーンX及びX+1が設けられる場合、これらは、クラスタ形態の二重マシーンのように動作するのが好ましい。
計算負荷をマシーンM1、M2...Mn全体にわたって分散させることができるときには、サーバーマシーンXを設ける必要はない。或いは、1つのマシーンで動作されるデータベース(マスタ/スレーブタイプオペレーション)は、ハウスキーピング機能に用いることができる。
図16は、実行すべき好ましい一般的な手順を示している。ロード161の開始後、実行される命令が順番に考慮され、全同期ルーチンがステップ162で示されるように検出される。JAVA言語では、これらは、「monitorenter」及び「monitorexit」命令である。他の言語では異なる項を使用する。
同期ルーチンが検出された場合、通常は別の命令をルーチンに挿入することによって修正される。或いは、修正命令をルーチンの前に挿入することもできる。修正が完了すると、ロード手順に進む。修正は、ステップ163で示されるように、「全ての他のマシーンでのロック取得」オペレーション及び「全ての他のマシーンでのロック解放」修正の形式を取るのが好ましい。
図17は、修正の特定の形式を示している。最初に、同期される構造、資産、又は資源(JAVAでは例えば50A、50X−50Yなどのクラス又はオブジェクトと呼ばれる)は、ステップ172によって示されるように全てのマシーンによってグローバルに使用できる名前又はタグが既に割り当てられている。これは、クラス又はオブジェクトが最初に初期化されるときに行われるのが好ましい。これは、サーバーマシーンXによって維持されているテーブルを介して非常に好都合に行われる。このテーブルはまた、クラス又はオブジェクトの同期状態を含む。好ましい実施形態において、このテーブルはまた、この資産の使用を要求しているマシーンのアイデンティティを記憶する待ち行列構成を含む。
図17のステップ173で示されるように、次の「ロック取得」要求がマシーンXに送信され、その後、送信マシーンは、ステップ174で示されるようにロック取得が確認されるのを待機する。従って、グローバル名が既にロックされている(すなわち、対応する資産が、ロックの取得を提案しているマシーン以外の別のマシーンによって使用中である)場合、これは、オブジェクト又はクラスが現在の所有者によってアンロックされるまで、オブジェクト又はクラスの提案された同期ルーチンを停止しなければならないことを意味する。
或いは、グローバル名がロックされていない場合、これは、他のマシーンがこのクラス又はオブジェクトを使用していないことを意味し、ロック取得の確認は直ちに受信される。ロック取得の確認を受信した後、ステップ175で示されるように、同期ルーチンの実行の続行が許可される。
図18は、ロックを放棄することを意図するアプリケーションプログラム実行中のマシーンによって行われる手順を示している。初期ステップは、ステップ181で示される。この提案しているマシーンのオペレーションは、ステップ183、184によって一時的に中断され、その後、返信がステップ184に対応してマシーンXから受信され、次いでステップ185で示されるように実行が再開される。任意選択的に、ステップ182で示されるように、マシーンが要求しているロックの解放は、マシーンXに行われている要求に先行してこのロックに対する「グローバル名」をルックアップするために行われる。このように、複数のマシーンの複数のロックは、相互に干渉することなく取得し解放することができる。
図19は、「ロック取得」問い合わせ(図17)に応答して、マシーンXによって行われる動作を示している。ステップ191で「ロック取得」要求を受け取った後、ステップ192及び193でロック状態が判定され、ノー、すなわち名付けられた資源がフリーでない場合、問い合わせしているマシーンのアイデンティティは、待機中の取得要求待ち行列(又は形式)にステップ194で追加される。或いは、答えがイエスであり、すなわち、名付けられた資源がフリーである場合、対応する返信がステップ197で送られる。次いで、待機している問い合わせ中のマシーンは、図17のステップ175を実行することによってこれに応じて同期ルーチンを実行することができる。イエスの応答に加えて、共有テーブルは、グローバルに名付けられた資産の状態が「ロック」に変更されるようにステップ196で更新される。
図20は、図18の「ロック解放」要求に応答してマシーンXによって行われる動作を示している。ステップ201で「ロック解放」要求を受け取った後、マシーンXは、任意選択的に、及び好ましくは、ロックを解放するよう要求しているマシーンが、ステップ202で示されるように実際にはロックの現在の所有者であることを確認する。次に、ステップ203で待ち行列状態が判定され、このロックを取得するよう待機しているものがいない場合、マシーンXは、ステップ207で示されるようにこのロックを共有テーブルで「未所有」としてマークし、任意選択的にステップ208によって示されるように、要求しているマシーンに解放の確認を返信する。これによって、要求しているマシーンが図18のステップ185を実行できるようになる。
或いは、イエス、すなわち他のマシーンがこのロックの取得を待機している場合、マシーンXは、ステップ204で示されるように待ち行列において次のマシーンによって現在取得されたものとしてこのロックをマークし、次にステップ205で、ロック取得の確認を待ち行列に並んだマシーンに送り、この結果、ステップ206で示されるように待機しているマシーンの待ち行列から新しいロック所有者を消去する。
同期ルーチンを修正する基本的概念が与えられると、この概念を実装することができる幾つかの種々の方法が存在する。
第1の実施形態において、特定のマシーン、例えばマシーンM2は、自己に同期ルーチンをロードし、これを修正し、次いで他のマシーンM1、M3...Mnの各々に(順次に又は同時に)修正同期ルーチンをロードする。「マスタ/スレーブ」と呼ぶ場合があるこの構成では、マシーンM1、M3、...Mnの各々が、マシーンM2によって与えられるものをロードする。
この「マスタ/スレーブ」構成の変形形態では、マシーンM2は、該マシーンM2に未修正の形式で同期ルーチンをロードし、次いで他のマシーンに同期ルーチン全体を削除して、修正コードをロードする。従ってこの場合、修正は、同期ルーチンのバイパスではなく、1つを除いた全てのマシーン上での同期ルーチンの削除である。
更に別の実施形態では、各マシーンは、同期ルーチンを受け取るが、これを修正し修正ルーチンをそのマシーンにロードする。これによって、各マシーンが行う修正をそのアーキテクチャ及びオペレーティングシステムに基づき僅かに異なるように最適化することができ、更に全ての他の類似の修正と整合を取ることができるようになる。
別の構成では、特定のマシーン、例えばM1は、未修正の同期ルーチンをロードし、全ての他のマシーンM2、M3...Mnは、オリジナルの同期ルーチンを削除し修正されたバージョンをロードするよう修正を行う。
全ての事例において、供給は、ブランチ(すなわち、M2がM1、M3、M4などの各々に直接提供する)又はカスケード或いはシーケンシャル(すなわち、M2がM1に印加し、次にM1がM3に供給し、次いでM3がM4に供給する、以下同じ)とすることができる。
更に別の構成では、マシーンM1からMnは、全ロード要求を追加のマシーンX(図15)に送ることができ、該追加マシーンXは、前述の方法のいずれかを介して修正を行い、修正ルーチンをマシーンM1からMnの各々に返し、次いで修正ルーチンをローカルにロードする。この構成では、マシーンM1からMnは、全ロード要求をマシーンXに転送し、マシーンXは、修正ルーチンを各マシーンに返す。マシーンXによって行われる修正は、本発明の範囲内で保護される修正の全てを含むことができる。
コンピュータ関連技術に熟練した人であれば、コンピュータコードで修正を作成する際に使用される4つの技術を認識することになる。第1は、オリジナル(ソース)言語で修正を行うことである。第2は、オリジナルコード(例えばJAVAでの)を中間表現(又は中間言語)に変換することである。この変換を行うと、修正がなされ、次いで逆変換される。これは、修正されたJAVAコードの要求結果をもたらす。
第3の可能性は、マシーンコードに(直接又は前述の中間言語を介して)変換することである。次にマシーンコードは修正された後、ロードされ実行される。第4の可能性は、オリジナルコードを中間表現に変換することであり、この中間表現は次に修正され、その後マシーンコードに変換される。
本発明は、全ての4つの修正ルートと、更にこのようなルートの2つ、3つ、又は4つ全部の組み合わせを包含する。
ここで図21−23を参照すると、2つのラップトップコンピュータ101及び102が示されている。コンピュータ101及び102は、必ずしも同一でなくともよく、実際には、1つはIBM又はIBMクローンで、他方がAPPLEコンピュータとすることができる。コンピュータ101及び102は、2つのモニタ105、115及び2つのキーボード106、116と、単一のマウス107とを有する。2つのマシーン101、102は、単一の同軸ケーブル又はツイストペアケーブル314手段によって相互接続されている。
2つのシンプルアプリケーションプログラムは、マシーン101、102の各々にダウンロードされ、このプログラムは上述のようにロードされるときに修正される。この実施形態において、第1アプリケーションは、シンプル計算器プログラムであり、モニタ105上に表示される計算器108のイメージをもたらす。第2プログラムは、異なる色であり且つ矩形ボックス310内をランダムに動き回る4つのカラーブロック109を表示するグラフィックプログラムである。同様にロード後に、ボックス310はモニタ105上に表示される。各アプリケーションはブロック109がモニタ105上でランダムに移動しているように独立して動作すると同時に、計算器108内の数字は数学的演算子(加算又は乗算など)と共に(マウス107を用いて)選択され、計算器108が結果を表示することができるようになる。
マウス107を用いて、ボックス310を「把持」し、これを右方向にモニタ105を越えてモニタ115上に移動させ、図22に示された状況に到るようにすることができる。この構成では、計算器アプリケーションがマシーン101上で処理されている間、ボックス310の表示をもたらすグラフィックアプリケーションはマシーン102上で処理されている。
しかしながら、図23に示されるようにマウス107を用いることで、図22に示されるように計算器108を右側にドラッグし、計算器108の一部をモニタ105、115の各々で表示させることができる。同様に、図22に示されるボックス310は、マウス107を用いて左側にドラッグすることができ、その結果、ボックス310は図23に示されるようにモニタ105、115の各々で部分的に表示されるようになる。この構成では、計算器オペレーションの部分は、マシーン101とマシーン102の一部上で実行されていると同時に、グラフィックアプリケーションの部分はマシーン101で実行されており、残りはマシーン102で実行されている。
上記は、本発明の幾つかの実施形態だけを説明しており、当業者であれば本発明の範囲から逸脱することなく本発明に対し修正を行うことができる点は明らかであろう。例えば、JAVAへの言及は、JAVA言語と更にJAVAプラットフォーム及びアーキテクチャの両方を含む。
プログラミング技術に熟練した者であれば、付加的なコード又は命令が既存のコード又は命令セットに挿入されてこれを修正する場合、既存のコード又は命令セットは、オフセット、分岐、属性、マークアップ、及び同様のものが作成されるような追加の修正(例えば、シーケンシャル命令の再ナンバリングによって)を必要とする場合があることを認識するであろう。
同様に、JAVA言語でのメモリロケーションは、例えばフィールド及びアレイタイプの両方を含む。上記の説明は、フィールドを扱っており、アレイタイプに必要な変更は、本質的に同じ準用である。また本発明は、Microsoft.NETプラットフォーム及びアーキテクチャ(VisualBasic、VisualC/C++、及びC#)のFORTRAN、C/C++、COBOL、BASICなどを含むJAVAに類似したプログラミング言語(手続き、宣言、及びオブジェクト指向を含む)に対して等しく適用可能である。
JAVA同期化ルーチンのコードが修正される上述の実施形態は、各マシーンM1...Mnのランタイムシステム(例えば、C及びJAVAで記述されたJAVA HOTSPOT VIRTUAL MACHINE)又はオペレーティングシステム(例えば、C及びアセンブラで記述されたLINUX)のいずれかが、通常はローカルマシーン(例えばM2)でロックを取得し、他のあらゆるマシーン(M1...Mn)では取得されないことになる仮定に基づく。JAVA同期化ルーチンを未修正のままにし、その代わりにロックをローカルに取得するLINUX又はHOTSPOTルーチンを修正することが可能であり、その結果、これに伴い他の全てのマシーンでも同様にロックを取得するようになる。このような構成を包含するために、用語「同期化ルーチン」は、JAVA同期化ルーチン、並びにJAVA同期化ルーチンとロックの取得及び解放を実行するLINUX又はHOTSPOTコードフラグメントとの「組み合わせ」の両方がその範囲に含まれることになると理解すべきである。
本明細書で使用される用語オブジェクト及びクラスは、JAVA環境から生じたものであり、ダイナミックリンクライブラリ(DLL)、或いはオブジェクトコードパッケージ、或いは関数ユニット又はメモリロケーションのような異なる環境から派生した類似語を包含するものとする。
本明細書で使用される用語「備える」(及びその文法的変形形態)は、「有する」又は「含む」といった包括的な意味で使用され、「だけからなる」という排他的意味では使用されない。
著作権表示
本特許出願は、著作権保護の下にある資料を含む。著作権所有者(出願人)は、審査の目的で公的に利用可能な関連する特許庁ファイルからこの特許明細書又は関連資料を複製することに異議はないが、これ以外は如何なるものも無断転載が禁じられている。特に、種々の命令は、著作権所有者によって具体的に文書による承諾なしにコンピュータに入力されるべきではない。
添付書A
以下は、JAVA言語でのプログラムリストである。
A1.この第1の抜粋は、修正コードの一部である。これは、コードアレイをサーチし、putstatic命令(opcode178)を見つけると、修正を実行する。
// 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
A2.この第2の抜粋は、DRT.alert()法の一部である。これは、呼び出されたときのDRT.alert()法の本体である。
// START
public static void alert(){
synchronized (ALERT_LOCK){
ALERT_LOCK.notify(); // Alerts a waiting DRT thread in the background.
}
}
// END
A3.この第3の抜粋は、DRT送信の一部である。このコードフラグメントは、別々のスレッドのDRTを示しており、通知された後にネットワーク全体に値を送信する。
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
A4.第4の抜粋は、DRT受信の一部である。これは、ネットワークを通じてDRT送信警報を受信するためのコードのフラグメントである。
// 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
A5.第5の抜粋は、修正が行われる前の例示的なアプリケーションである。
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
A6.第6の抜粋は、修正が実行された後の5と同様の例示的なアプリケーションである。修正は下線で強調されている。
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
A7.第7の抜粋は、抜粋5及び6で使用された例示的なアプリケーションのソースコードである。
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;
}
}
A8.第8の抜粋は、「分散ランタイム」をアラートし変更された値を伝播するFieldAlertのソースコードである。
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();
}
}
}
}
A9.第9の抜粋は、FieldAlertを介してアラートされた変更値を伝播するFieldSendのソースコードである。
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());
}
}
}
A10.第10の抜粋は、FieldSendを介して送信される伝播された変更値を受信するFieldReceiveのソースコードである。
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());
}
}
}
A11.FieldLoader.java
この抜粋は、ロードされているときにアプリケーションを修正するFieldLoaderのソースコードである。
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);
}
}
}
A12.Attribute_info.java
ClassFiles内のattribute_info構造を表わすためのコンビエンスクラス
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);
}
}
}
A13.ClassFile.java
ClassFile構造を表わすためのコンビエンスクラス
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();
}
}
A14.Code_attribute.java
ClassFiles内のCode_attribute構造を表わすためのコンビエンスクラス
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);
}
}
A15.COSTANT_Class_info.java
ClassFiles内のCOSTANT_Class_info構造を表わすためのコンビエンスクラス
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);
}
}
A16.CONSTANT_Double_info.java
ClassFiles内のCONSTANT_Double_info構造を表わすためのコンビエンスクラス
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);
}
}
A17.CONSTANT_Fieldref_info.java
ClassFiles内のCONSTANT_Fieldref_info構造を表わすためのコンビエンスクラス
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);
}
}
A18.CONSTANT_Float_info.java
ClassFiles内のCONSTANT_Float_info構造を表わすためのコンビエンスクラス
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);
}
}
A19.CONSTANT_Integer_info.java
ClassFiles内のCONSTANT_Integer_info構造を表わすためのコンビエンスクラス
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);
}
}
A20.CONSTANT_InterfaceMethodref_info.java
ClassFiles内のCONSTANT_InterfaceMethodref_info構造を表わすためのコンビエンスクラス
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);
}
}
A21.CONSTANT_Long_info.java
ClassFiles内のCONSTANT_Long_info構造を表わすためのコンビエンスクラス
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);
}
}
A22.CONSTANT_Methodref_info.java
ClassFiles内のCONSTANT_Methodref_info構造を表わすためのコンビエンスクラス
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);
}
}
A23.CONSTANT_NameAndType_info.java
ClassFiles内のCONSTANT_NameAndType_info構造を表わすためのコンビエンスクラス
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);
}
}
A24.CONSTANT_String_info.java
ClassFiles内のCONSTANT_String_info構造を表わすためのコンビエンスクラス
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);
}
}
A25.CONSTANT_Utf8_info.java
ClassFiles内のCONSTANT_Utf8_info構造を表わすためのコンビエンスクラス
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;
}
}
A26.ConstantValue_attribute.java
ClassFiles内のConstantValue_attribute構造を表わすためのコンビエンスクラス
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);
}
}
A27.cp_info.java
ClassFiles内のcp_info構造を表わすためのコンビエンスクラス
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();
}
}
A28.Deprecated_attrbiute.java
ClassFiles内のDeprecated_attrbiute構造を表わすためのコンビエンスクラス
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);
}
}
A29.Exceptions_attribute.java
ClassFiles内のExceptions_attribute構造を表わすためのコンビエンスクラス
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]);
}
}
A30.field_info.java
ClassFiles内のfield_info構造を表わすためのコンビエンスクラス
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);
}
}
A31.InnerClasses_attribute.java
ClassFiles内のInnerClasses_attribute構造を表わすためのコンビエンスクラス
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);
}
}
}
A32.LineNumberTable_attribute.java
ClassFiles内のLineNumberTable_attribute構造を表わすためのコンビエンスクラス
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);
}
}
}
A33.LocalVariableTable_attribute.java
ClassFiles内のLocalVariableTable_attribute構造を表わすためのコンビエンスクラス
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);
}
}
}
A34.method_info.java
ClassFiles内のmethod_info構造を表わすためのコンビエンスクラス
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);
}
}
A35.SourceFile_attribute.java
ClassFiles内のSourceFile_attribute構造を表わすためのコンビエンスクラス
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);
}
}
A36.Synthetic_attribute.java
ClassFiles内のSynthetic_attribute構造を表わすためのコンビエンスクラス
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);
}
}
添付書D1
Method void run()
0 getstatic #2 <Field java.lang.Object LOCK>
3 dup
4 astore_1
5 monitorenter
6 getstatic #3 <Field int counter>
9 iconst_1
10 iadd
11 putstatic #3 <Field int counter>
14 aload_1
15 monitorexit
16 return
添付書D2
Method void run()
0 getstatic #2 <Field java.lang.Object LOCK>
3 dup
4 astore_1
5 dup
6 monitorenter
7 invokestatic #23 <Method void acquireLock(java.lang.Object)>
10 getstatic #3 <Field int counter>
13 iconst_1
14 iadd
15 putstatic #3 <Field int counter>
18 aload_1
19 dup
20 invokestatic #24 <Method void releaseLock(java.lang.Object)>
23 monitorexit
24 return
添付書D3
import java.lang.*;

public class example{

/** Shared static field. */
public final static Object LOCK = new Object();

/** Shared static field. */
public static int counter = 0;

/** Example method using synchronization. This method serves to
illustrate the use of synchronization to implement thread-safe
modification of a shared memory location by potentially multiple
threads. */
public void run(){

// First acquire the lock, otherwise any memory writes we do will be
// prone to race-conditions.
synchronized (LOCK){

// Now that we have acquired the lock, we can safely modify memory
// in a thread-safe manner.
counter++;
}
}
}
添付書D4
import java.lang.*;
import java.util.*;
import java.net.*;
import java.io.*;

public class LockClient{

/** 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 ACQUIRE_LOCK = 10;
public final static int RELEASE_LOCK = 20;

/** LockServer network values. */
public final static String serverAddress =
System.getProperty(“LockServer_network_address”);
public final static int serverPort =
Integer.parseInt(System.getProperty(“LockServer_network_port”));

/** Table of global ID's for local objects. (hashcode-to-globalID
mappings) */
public final static Hashtable hashCodeToGlobalID = new Hashtable();

/** Called when an application is to acquire a lock. */
public static void acquireLock(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 LockServer, which will grant us
// the global lock.
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 lock server.
out.writeInt(ACQUIRE_LOCK);
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.”);
}

// Close down the connection.
out.writeInt(CLOSE);
out.flush();
out.close();
in.close();

socket.close();// Make sure to close the socket.
// This is a good acknowledgement, thus we can return now because
// global lock is now acquired.
return;

}catch (IOException e){
throw new AssertionError(“Exception: ” + e.toString());
}
}
/** Called when an application is to release a lock. */
public static void releaseLock(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 LockServer, which records us as
// the owner of the global lock for object 'o'.
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 lock server.
out.writeInt(RELEASE_LOCK);
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.”);
}

// Close down the connection.
out.writeInt(CLOSE);
out.flush();
out.close();
in.close();
socket.close(); // Make sure to close the socket.
// This is a good acknowledgement, return because global lock is
// now released.
return;
}catch (IOException e){
throw new AssertionError(“Exception: ” + e.toString());
}
}
}
添付書D5
import java.lang.*;
import java.util.*;
import java.net.*;
import java.io.*;

public class LockServer 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 ACQUIRE_LOCK = 10;
public final static int RELEASE_LOCK = 20;

/** LockServer network values. */
public final static int serverPort = 20001;

/** Table of lock records. */
public final static Hashtable locks = new Hashtable();

/** Linked list of waiting LockManager objects. */
public LockServer next = null;

/** Address of remote LockClient. */
public final String address;

/** Private input/output objects. */
private Socket socket = null;
private DataOutputStream outputStream;
private DataInputStream inputStream;

public static void main(String[] s)
throws Exception{

System.out.println(“LockServer_network_address=”
+ InetAddress.getLocalHost().getHostAddress());
System.out.println(“LockServer_network_port=” + serverPort);

// Create a serversocket to accept incoming lock operation
// connections.
ServerSocket serverSocket = new ServerSocket(serverPort);

while (!Thread.interrupted()){
// Block until an incoming lock operation connection.
Socket socket = serverSocket.accept();

// Create a new instance of LockServer to manage this lock
// operation connection.
new Thread(new LockServer(socket)).start();
}
}
/** Constructor. Initialise this new LockServer instance with necessary
resources for operation. */
public LockServer(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 lock 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 == ACQUIRE_LOCK){ // This is an
// ACQUIRE_LOCK
// operation.

// Read in the globalID of the object to be locked.
int globalID = inputStream.readInt();

// Synchronize on the locks table in order to ensure thread-
// safety.
synchronized (locks){

// Check for an existing owner of this lock.
LockServer lock = (LockServer) locks.get(
new Integer(globalID));

if (lock == null){// No-one presently owns this lock,
// so acquire it.

locks.put(new Integer(globalID), this);

acquireLock(); // Signal to the client the
// successful acquisition of this
// lock.

}else{ // Already owned. Append ourselves
// to end of queue.

// Search for the end of the queue. (Implemented as
// linked-list)
while (lock.next != null){
lock = lock.next;
}

lock.next = this;// Append this lock request at end.
}
}
}else if (command == RELEASE_LOCK){// This is a
// RELEASE_LOCK
// operation.

// Read in the globalID of the object to be locked.
int globalID = inputStream.readInt();

// Synchronize on the locks table in order to ensure thread-
// safety.
synchronized (locks){

// Check to make sure we are the owner of this lock.
LockServer lock = (LockServer) locks.get(
new Integer(globalID));

if (lock == null){
throw new AssertionError(“Unlocked. Release failed.”);
}else if (lock.address != this.address){
throw new AssertionError(“Trying to release a lock ”
+ “which this client doesn't own. Release ”
+ “failed.”);
}

lock = lock.next;
lock.acquireLock();// Signal to the client the
// successful acquisition of this
// lock.

// Shift the linked list of pending acquisitions forward
// by one.
locks.put(new Integer(globalID), lock);

// Clear stale reference.
next = null;
}

releaseLock(); // Signal to the client the successful
// release of this lock.

}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;
}
}
/** Send a positive acknowledgement of an ACQUIRE_LOCK operation. */
public void acquireLock() throws IOException{
outputStream.writeInt(ACK);
outputStream.flush();
}

/** Send a positive acknowledgement of a RELEASE_LOCK operation. */
public void releaseLock() throws IOException{
outputStream.writeInt(ACK);
outputStream.flush();
}
}
添付書D6
Lock Loader.java
この引用は、ロード時にアプリケーションを修正するLock Loaderのソースコードである。
import java.lang.*;
import java.io.*;
import java.net.*;

public class LockLoader extends URLClassLoader{

public LockLoader(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 enterindex and exitindex.
int enterindex = -1;
int exitindex = -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) == 194){ // Opcode for a
// MONITORENTER
// instruction.
changed = true;

// Next, realign the code array, making room for the
// insertions.
byte[][] code2 = new byte[ca.code.length+2][];
System.arraycopy(ca.code, 0, code2, 0, z);
code2[z+1] = ca.code[z];
System.arraycopy(ca.code, z+1, code2, z+3,
ca.code.length-(z+1));
ca.code = code2;

// Next, insert the DUP instruction.
ca.code[z] = new byte[1];
ca.code[z][0] = (byte) 89;

// Finally, insert the INVOKESTATIC instruction.
if (enterindex == -1){
// This is the first time this class is encourtering the
// acquirelock 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(“LockClient”);
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(“acquireLock”);
cf.constant_pool[cf.constant_pool.length-4] = u1;

u1 = new CONSTANT_Utf8_info(“(Ljava/lang/Object;)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;
enterindex = cf.constant_pool.length-1;
}
ca.code[z+2] = new byte[3];
ca.code[z+2][0] = (byte) 184;
ca.code[z+2][1] = (byte) ((enterindex >> 8) & 0xff);
ca.code[z+2][2] = (byte) (enterindex & 0xff);

// And lastly, increase the CODE_LENGTH and ATTRIBUTE_LENGTH
// values.
ca.code_length += 4;
ca.attribute_length += 4;

z += 1;

}else if ((ca.code[z][0] & 0xff) == 195){// Opcode for a
// MONITOREXIT
// instruction.
changed = true;

// Next, realign the code array, making room for the
// insertions.
byte[][] code2 = new byte[ca.code.length+2][];
System.arraycopy(ca.code, 0, code2, 0, z);
code2[z+1] = ca.code[z];
System.arraycopy(ca.code, z+1, code2, z+3,
ca.code.length-(z+1));
ca.code = code2;

// Next, insert the DUP instruction.
ca.code[z] = new byte[1];
ca.code[z][0] = (byte) 89;

// Finally, insert the INVOKESTATIC instruction.
if (exitindex == -1){
// This is the first time this class is encourtering the
// acquirelock 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(“LockClient”);
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(“releaseLock”);
cf.constant_pool[cf.constant_pool.length-4] = u1;

u1 = new CONSTANT_Utf8_info(“(Ljava/lang/Object;)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;
exitindex = cf.constant_pool.length-1;
}
ca.code[z+2] = new byte[3];
ca.code[z+2][0] = (byte) 184;
ca.code[z+2][1] = (byte) ((exitindex >> 8) & 0xff);
ca.code[z+2][2] = (byte) (exitindex & 0xff);

// And lastly, increase the CODE_LENGTH and ATTRIBUTE_LENGTH
// values.
ca.code_length += 4;
ca.attribute_length += 4;

z += 1;
}
}
// 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);
}

}
}
従来のコンピュータの内部アーキテクチャを示す概略図である。 公知の対称型多重プロセッサの内部アーキテクチャを示す概略図である。 従来技術の分散コンピューティングを示す概略図である。 クラスタを使用した従来技術のネットワークコンピューティングを示す概略図である。 本発明の第1の実施形態に従って同じアプリケーションプログラムを実行する複数のマシーンを示す概略ブロック図である。 JAVAコードを動作させ、これによってJAVA仮想マシーンを構成するように配置された従来技術のコンピュータを示す概略図である。 図6に類似しているが、好ましい実施形態に従ってコードの初期ロードを示す図である。 図5に類似しているが、図7に示された方式でJAVAコードを各々が実行する複数のコンピュータの相互接続を示す図である。 ネットワーク内の各マシーンでの同じアプリケーションのロード中に行われる手順を示すフローチャートである。 図9の手順に類似した修正された手順を示すフローチャートである。 メモリ更新の第1の実施形態を利用して図8のマシーンで実行されるマルチスレッド処理を示す概略図である。 図11に類似した他の実施形態を示す概略図である。 図8のコンピュータに対するマルチスレッドメモリ更新を示す図である。 JAVAコードで動作し、これによってJAVA仮想マシーンを構成するように配置された従来技術のコンピュータを示す概略図である。 アプリケーションプログラムを実行し、付加的なサーバーマシーンXによってサービスされるn個のマシーンを示す概略図である。 monitorenter及びexitルーチンの修正を示すフローチャートである。 ロックの取得要求におけるマシーンの処理に従うプロセスを示すフローチャートである。 ロックの解放の要求を示すフローチャートである。 図17の要求に対するサーバーマシーンXの応答のフローチャートである。 図18の要求に対するサーバーマシーンXの応答を示すフローチャートである。 複数のアプリケーションを同時に実行するために相互接続され、両方とも単一のコンピュータ上で実行されるアプリケーションを備えた2つのラップトップコンピュータを示す概略図である。 図21に類似した図であり、各コンピュータで実行される1つのアプリケーションを備えた図21の装置を示す図である。 図21及び22に類似した図であり、両方のコンピュータ上で同時に実行される両方のアプリケーションを備えた図21の装置を示す図である。
符号の説明
50 アプリケーション
53 ネットワーク
71 DRT

Claims (30)

  1. 単一のコンピュータでのみ動作するように各々記述されているが、通信ネットワークによって相互接続された複数のコンピュータ上で同時に実行される少なくとも1つのアプリケーションプログラムを有する多重コンピュータシステムであって、
    前記アプリケーションプログラムの異なる部分が前記コンピュータのうちの異なるコンピュータ上でほぼ同時に実行され、前記各部分において、実質的に同一な複数のオブジェクトが前記対応するコンピュータに各々作成され、各々が実質的に同一の名前を有し、前記システムは、前記コンピュータの全てに利用可能なロック手段を含み、コンピュータ内の名前を付けられたオブジェクトを利用したいと望んでいるあらゆるコンピュータが、前記ロック手段から許可ロックを取得し、前記許可ロックにより前記利用が許可され、前記許可ロックが放棄されるまで前記他のコンピュータ全てがこれらの対応する名前を付けられたオブジェクトを利用するのが阻止されることを特徴とする多重コンピュータシステム。
  2. 前記ロック手段は、ロック取得ルーチンとロック解放ルーチンとを含み、前記ルーチンの両方は、前記全てのコンピュータ上で実行される前記アプリケーションプログラムになされた修正に含まれることを特徴とする請求項1に記載のシステム。
  3. 前記ロック手段は、いずれかの前記コンピュータによって使用される前記名前を付けられたオブジェクト、前記各オブジェクトのロック状態、及びいずれかの未決のロック取得の待ち行列をリストする共有テーブルを更に含むことを特徴とする請求項2に記載のシステム。
  4. 前記ロック手段は、前記アプリケーションプログラムを実行しておらず、前記通信ネットワークに接続されている追加のコンピュータ内に位置付けられることを特徴とする請求項3に記載のシステム。
  5. 前記各アプリケーションプログラムは、前記ロック取得ルーチン及び前記ロック解放ルーチンを挿入して、前記アプリケーションプログラムがオブジェクトに対するロックをそれぞれ取得及び解放する各インスタンスを修正することによって、ロード前、ロード中、又はロード後に修正されることを特徴とする請求項2に記載のシステム。
  6. 前記アプリケーションプログラムは、ロード時の再コンパイル、ロード前の事前コンパイル、ロード前のコンパイル、実行時コンパイル、及びロード後で且つアプリケーションプログラムの前記関連部分の実行前の再コンパイルからなる手順のグループから選択される手順に従って修正されることを特徴とする請求項3に記載のシステム。
  7. 前記修正アプリケーションプログラムは、マスタ/スレーブ転送、ブランチ転送、及びカスケード転送からなるグループから選択される手順に従って前記コンピュータの全てに転送されることを特徴とする請求項2に記載のシステム。
  8. 通信リンクを介して相互接続され、単一のコンピュータでのみ動作するように各々記述されている少なくとも1つのアプリケーションプログラムを同時に実行する複数のコンピュータであって、
    前記各コンピュータが前記アプリケーションプログラムの異なる部分をほぼ同時に実行し、前記アプリケーションプログラム部分を動作中の前記各コンピュータは、前記各コンピュータに物理的に位置付けられたローカルメモリ内にあるオブジェクトだけを利用し、前記各コンピュータによって利用される前記ローカルメモリのコンテンツは、基本的に類似しているが、各瞬間では同一でなく、前記コンピュータの全てのコンピュータが、1つのコンピュータだけによる前記ローカルオブジェクトの利用を許可するロック取得ルーチン及びロック解放ルーチンを有し、前記複数のコンピュータの残りの各々は、これらの対応するオブジェクトの利用からロックアウトされることを特徴とする複数のコンピュータ。
  9. 前記又は前記各アプリケーションプログラムに割り当てられたローカルメモリ容量が実質的に同一であり、前記又は前記各アプリケーションプログラムが利用可能な総メモリ容量が、前記割り当てられたメモリ容量であることを特徴とする請求項8に記載の複数のコンピュータ。
  10. 前記分散更新手段の全ては、前記ローカルメモリ読み取り速度よりも遅いデータ転送速度で前記通信リンクを介して伝達することを特徴とする請求項8に記載の複数のコンピュータ。
  11. 前記コンピュータの少なくとも幾つかは、種々の製造業者によって製造され、及び/又は種々のオペレーティングシステムを有することを特徴とする請求項8に記載の複数のコンピュータ。
  12. 単一のコンピュータでのみ動作するように各々記述されている少なくとも1つのアプリケーションプログラムを複数のコンピュータ上で同時に実行する方法であって、前記コンピュータは、通信ネットワークによって相互接続されており、前記方法が、
    (i)前記コンピュータのうちの異なるコンピュータ上で前記アプリケーションプログラムの異なる部分を実行し、前記各部分について前記対応するコンピュータ内に実質的に同一な複数のオブジェクトを各々作成し、各々に実質的に同一の名前を持たせる段階と、
    (ii)コンピュータ内の名前を付けられたオブジェクトを利用することを意図する前記コンピュータのいずれにも、前記利用を許可し、前記許可ロックが放棄されるまで前記他のコンピュータの全てがこれらの対応する名前を付けられたオブジェクトの利用を阻止する許可ロックを取得するように要求する段階と、
    を含む方法。
  13. (iii)前記通信ネットワークを介して前記コンピュータ間で伝達するための分散ランタイム手段を前記各コンピュータに提供する段階を更に含む請求項12に記載の方法。
  14. (iv)前記各分散ランタイム手段によってアクセス可能であり、オブジェクトに現在アクセスする必要のあるあらゆるコンピュータのアイデンティティを前記オブジェクトのアイデンティティと共に記憶される共有テーブルを提供する段階を更に含む請求項13に記載の方法。
  15. 前記オブジェクトへのアクセスを求める前記コンピュータの数のカウントを記憶するカウンタ手段を前記共有テーブルに関連付ける段階(v)を更に含む請求項14に記載の方法。
  16. 前記共有プログラムが実行されておらず、前記共有テーブル及びカウンタをホストする追加のコンピュータを提供する段階であって、該追加のコンピュータが前記通信ネットワークに接続されている提供段階(vi)を更に含む求項15に記載の方法。
  17. 単一のコンピュータでのみ動作するように記述されているが、通信ネットワークを介して相互接続された複数のコンピュータの異なるコンピュータ上でその異なる部分が各々ほぼ同時に実行されることになるアプリケーションプログラムの矛盾のない同期を保証する方法であって、前記方法が、
    (i)ロード時、又はロード前、又はロード後に前記アプリケーションプログラムを精査して、同期ルーチンを定義する各プログラム段階を検出する段階と、
    (ii)前記同期ルーチンを修正して1つだけのコンピュータによるオブジェクトの利用を保証し、前記残りのコンピュータ全てがこれらの対応するオブジェクトを同時に利用することを阻止する段階と、
    を含む方法。
  18. 前記段階(ii)が、
    (iii)前記コンピュータの1つで前記同期ルーチンをロードし実行する段階と、
    (iv)前記1つのコンピュータによって前記同期ルーチンを修正する段階と、
    (v)前記修正された同期ルーチンを前記残りのコンピュータの各々に転送する段階と、
    を含む請求項17に記載の方法。
  19. 前記修正された同期ルーチンは、前記1つのコンピュータによって前記残りのコンピュータの各々に直接提供されることを特徴とする請求項18に記載の方法。
  20. 前記修正された同期ルーチンは、前記1つのコンピュータから前記残りのコンピュータの各々に順次にカスケード方式で提供されることを特徴とする請求項18に記載の方法。
  21. 前記段階(ii)が、
    (vi)前記コンピュータの1つに前記同期ルーチンをロードし修正する段階と、
    (vii)前記1つのコンピュータが前記残りのコンピュータの各々に前記未修正の同期ルーチンを送信する段階と、
    (viii)前記残りのコンピュータの各々が前記同期ルーチンを受信した後に前記同期ルーチンを修正する段階と、
    を含む請求項17に記載の方法。
  22. 前記未修正の同期ルーチンは、前記1つのコンピュータによって前記残りのコンピュータの各々に直接提供されることを特徴とする請求項21に記載の方法。
  23. 前記未修正の同期ルーチンは、前記1つのコンピュータから前記残りのコンピュータの各々に順次にカスケード方式で提供されることを特徴とする請求項21に記載の方法。
  24. (ix)ロード時の再コンパイル、ロード前の事前コンパイル、ロード前のコンパイル、実行時コンパイル、及びロード後で且つアプリケーションプログラムの関連部分の実行前の再コンパイルからなる手順のグループから選択される手順を利用して前記アプリケーションプログラムを修正する段階を更に含む請求項17に記載の方法。
  25. (x)マスタ/スレーブ転送、ブランチ転送、及びカスケード転送からなるグループから選択される手順を利用して前記コンピュータの全てに前記修正アプリケーションプログラムを転送する段階を更に含む請求項17に記載の方法。
  26. 単一のコンピュータ上でのみ動作するように記述された単一のアプリケーションプログラムの個々のスレッドが、通信リンクを介して相互接続された複数のコンピュータのうちの対応するコンピュータ上で各々同時に処理されるマルチスレッド処理コンピュータオペレーションにおいて、
    各スレッドを処理する前記コンピュータに物理的に関連付けられたローカルメモリ内のオブジェクトは、他の前記各コンピュータのローカルメモリ内に対応するオブジェクトを有し、前記コンピュータの1つだけがオブジェクトを利用することを許可する段階と、前記残りのコンピュータの全てがこれらの対応するオブジェクトを同時に利用するのを阻止する段階とを含む改良方法。
  27. 1つの前記スレッドに関連付けられたメモリに常駐し且つ利用されることになるオブジェクトは、前記1つのスレッドのコンピュータによって他の前記コンピュータ全てがアクセス可能な共有テーブルに伝達されるアイデンティティを有することを特徴とする請求項26に記載の改良方法。
  28. 1つの前記スレッドに関連付けられたメモリに常駐し且つ利用されることになるオブジェクトは、別の前記スレッドに関連付けられた前記コンピュータに送信されるアイデンティティを有し、これによって前記他のコンピュータ全てがアクセス可能な共有テーブルに転送されることを特徴とする請求項26に記載の改良方法。
  29. 記憶媒体内に記憶され、請求項12又は17に記載される方法の実行を複数のコンピュータに許可するように動作可能なプログラム命令のセットを含むコンピュータプログラム製品。
  30. 通信ネットワークを介して相互接続された複数のコンピュータにおいて、単一のコンピュータでのみ動作するように各々記述されているが前記コンピュータ上で同時に実行されるアプリケーションプログラムの矛盾のない初期化を保証するよう動作可能な複数のコンピュータであって、前記コンピュータは、請求項12又は17に記載の方法を実行するようプログラムされており、或いは請求項29に記載のコンピュータプログラム製品がロードされていることを特徴とする複数のコンピュータ。
JP2007508675A 2004-04-22 2005-04-22 同期化を伴う多重コンピュータアーキテクチャ Pending JP2007534064A (ja)

Applications Claiming Priority (2)

Application Number Priority Date Filing Date Title
AU2004902146A AU2004902146A0 (en) 2004-04-22 Modified Computer Architecture
PCT/AU2005/000579 WO2005103925A1 (en) 2004-04-22 2005-04-22 Multiple computer architecture with synchronization

Publications (1)

Publication Number Publication Date
JP2007534064A true JP2007534064A (ja) 2007-11-22

Family

ID=35197170

Family Applications (4)

Application Number Title Priority Date Filing Date
JP2007508674A Pending JP2007534063A (ja) 2004-04-22 2005-04-22 オブジェクトの初期化を伴う改良型コンピュータアーキテクチャ
JP2007508675A Pending JP2007534064A (ja) 2004-04-22 2005-04-22 同期化を伴う多重コンピュータアーキテクチャ
JP2007508677A Pending JP2007534066A (ja) 2004-04-22 2005-04-22 複製メモリフィールドを備えたマルチコンピュータアーキテクチャ
JP2007508676A Pending JP2007534065A (ja) 2004-04-22 2005-04-22 オブジェクトファイナライズによる改良型コンピュータアーキテクチャ

Family Applications Before (1)

Application Number Title Priority Date Filing Date
JP2007508674A Pending JP2007534063A (ja) 2004-04-22 2005-04-22 オブジェクトの初期化を伴う改良型コンピュータアーキテクチャ

Family Applications After (2)

Application Number Title Priority Date Filing Date
JP2007508677A Pending JP2007534066A (ja) 2004-04-22 2005-04-22 複製メモリフィールドを備えたマルチコンピュータアーキテクチャ
JP2007508676A Pending JP2007534065A (ja) 2004-04-22 2005-04-22 オブジェクトファイナライズによる改良型コンピュータアーキテクチャ

Country Status (12)

Country Link
EP (5) EP1763774B1 (ja)
JP (4) JP2007534063A (ja)
KR (1) KR101209023B1 (ja)
CN (2) CN101908001B (ja)
BR (1) BRPI0508929A (ja)
CA (1) CA2563900C (ja)
EA (1) EA009926B1 (ja)
IL (1) IL178527A (ja)
MX (1) MXPA06012209A (ja)
NZ (1) NZ550480A (ja)
WO (5) WO2005103927A1 (ja)
ZA (1) ZA200608766B (ja)

Families Citing this family (46)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US7844665B2 (en) 2004-04-23 2010-11-30 Waratek Pty Ltd. Modified computer architecture having coordinated deletion of corresponding replicated memory locations among plural computers
US7707179B2 (en) 2004-04-23 2010-04-27 Waratek Pty Limited Multiple computer architecture with synchronization
US7849452B2 (en) 2004-04-23 2010-12-07 Waratek Pty Ltd. Modification of computer applications at load time for distributed execution
WO2006110937A1 (en) 2005-04-21 2006-10-26 Waratek Pty Limited Modified computer architecture with coordinated objects
CN101283344B (zh) 2005-10-10 2010-10-06 瓦拉泰克有限公司 具有增强的存储器清除的多计算机系统
WO2007041760A1 (en) * 2005-10-10 2007-04-19 Waratek Pty Limited Modified machine architecture with advanced synchronization
AU2006301908B2 (en) * 2005-10-10 2011-09-15 Waratek Pty Limited Modified machine architecture with machine redundancy
CN101283343B (zh) * 2005-10-10 2010-05-19 瓦拉泰克有限公司 具有部分存储器更新的改进的机器体系结构
WO2007041764A1 (en) * 2005-10-10 2007-04-19 Waratek Pty Limited Failure resistant multiple computer system and method
AU2006301911B2 (en) * 2005-10-10 2010-12-23 Waratek Pty Limited Failure resistant multiple computer system and method
EP1934776A4 (en) * 2005-10-10 2009-05-06 Waratek Pty Ltd REPLICATION OF GRAPHICS OF OBJECTS
WO2007041761A1 (en) * 2005-10-10 2007-04-19 Waratek Pty Limited Modified machine architecture with machine redundancy
CN101288062B (zh) * 2005-10-17 2012-03-21 瓦拉泰克有限公司 开销减少的多机器体系结构
US7958322B2 (en) 2005-10-25 2011-06-07 Waratek Pty Ltd Multiple machine architecture with overhead reduction
US7849369B2 (en) 2005-10-25 2010-12-07 Waratek Pty Ltd. Failure resistant multiple computer system and method
US8015236B2 (en) 2005-10-25 2011-09-06 Waratek Pty. Ltd. Replication of objects having non-primitive fields, especially addresses
US7581069B2 (en) 2005-10-25 2009-08-25 Waratek Pty Ltd. Multiple computer system with enhanced memory clean up
US7761670B2 (en) 2005-10-25 2010-07-20 Waratek Pty Limited Modified machine architecture with advanced synchronization
US7660960B2 (en) 2005-10-25 2010-02-09 Waratek Pty, Ltd. Modified machine architecture with partial memory updating
AU2007304895A1 (en) * 2006-10-05 2008-04-10 Waratek Pty Limited Advanced contention detection
US20080133884A1 (en) * 2006-10-05 2008-06-05 Holt John M Multiple network connections for multiple computers
US20080140863A1 (en) * 2006-10-05 2008-06-12 Holt John M Multiple communication networks for multiple computers
US20080140858A1 (en) 2006-10-05 2008-06-12 Holt John M Switch protocol for network communications
US20080141092A1 (en) * 2006-10-05 2008-06-12 Holt John M Network protocol for network communications
WO2008040074A1 (en) * 2006-10-05 2008-04-10 Waratek Pty Limited Contention detection with data consolidation
US20080140970A1 (en) * 2006-10-05 2008-06-12 Holt John M Advanced synchronization and contention resolution
US20080133869A1 (en) * 2006-10-05 2008-06-05 Holt John M Redundant multiple computer architecture
US20080140801A1 (en) * 2006-10-05 2008-06-12 Holt John M Multiple computer system with dual mode redundancy architecture
WO2008040065A1 (en) * 2006-10-05 2008-04-10 Waratek Pty Limited Contention detection and resolution
US8090926B2 (en) 2006-10-05 2012-01-03 Waratek Pty Ltd. Hybrid replicated shared memory
US20080133692A1 (en) * 2006-10-05 2008-06-05 Holt John M Multiple computer system with redundancy architecture
US20080126572A1 (en) * 2006-10-05 2008-05-29 Holt John M Multi-path switching networks
US20080126322A1 (en) * 2006-10-05 2008-05-29 Holt John M Synchronization with partial memory replication
US20080127213A1 (en) * 2006-10-05 2008-05-29 Holt John M Contention resolution with counter rollover
US20080130631A1 (en) * 2006-10-05 2008-06-05 Holt John M Contention detection with modified message format
US20100054254A1 (en) * 2006-10-05 2010-03-04 Holt John M Asynchronous data transmission
WO2008040076A1 (en) * 2006-10-05 2008-04-10 Waratek Pty Limited Contention resolution with echo cancellation
US8095616B2 (en) 2006-10-05 2012-01-10 Waratek Pty Ltd. Contention detection
US20080133861A1 (en) * 2006-10-05 2008-06-05 Holt John M Silent memory reclamation
WO2008040083A1 (en) * 2006-10-05 2008-04-10 Waratek Pty Limited Adding one or more computers to a multiple computer system
US8316190B2 (en) 2007-04-06 2012-11-20 Waratek Pty. Ltd. Computer architecture and method of operation for multi-computer distributed processing having redundant array of independent systems with replicated memory and code striping
KR101778825B1 (ko) 2010-05-03 2017-09-14 메르크 파텐트 게엠베하 제형물 및 전자 소자
JP5625621B2 (ja) 2010-08-25 2014-11-19 富士通株式会社 検出装置、方法、及びプログラム
CN105490908A (zh) * 2014-09-16 2016-04-13 中兴通讯股份有限公司 目标资源占用情况的处理方法及装置
EP3451259A1 (en) * 2017-09-01 2019-03-06 Unify Patente GmbH & Co. KG Computer-implemented method of performing a real-time collaboration session, collaborative platform for performing real-time collaboration sessions, and collaborative chat post object
CN110069243B (zh) * 2018-10-31 2023-03-03 上海奥陶网络科技有限公司 一种java程序线程优化方法

Citations (8)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JPH01297759A (ja) * 1988-05-26 1989-11-30 Tokyo Electric Power Co Inc:The ブロードキャストメモリ方式分散コンピュータシステム
JPH02132543A (ja) * 1988-11-12 1990-05-22 Nec Corp 情報処理装置
WO1995008809A2 (en) * 1993-09-24 1995-03-30 Oracle Corporation Method and apparatus for data replication
US5488723A (en) * 1992-05-25 1996-01-30 Cegelec Software system having replicated objects and using dynamic messaging, in particular for a monitoring/control installation of redundant architecture
WO2002044835A2 (en) * 2000-11-28 2002-06-06 Gingerich Gregory L A method and system for software and hardware multiplicity
US6625751B1 (en) * 1999-08-11 2003-09-23 Sun Microsystems, Inc. Software fault tolerant computer system
WO2003083614A2 (en) * 2002-03-25 2003-10-09 Eternal Systems, Inc. Transparent consistent active replication of multithreaded application programs
US20040073828A1 (en) * 2002-08-30 2004-04-15 Vladimir Bronstein Transparent variable state mirroring

Family Cites Families (7)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
ATE180586T1 (de) * 1990-11-13 1999-06-15 Ibm Paralleles assoziativprozessor-system
US5960087A (en) * 1996-07-01 1999-09-28 Sun Microsystems, Inc. Distributed garbage collection system and method
US6072953A (en) * 1997-09-30 2000-06-06 International Business Machines Corporation Apparatus and method for dynamically modifying class files during loading for execution
US6324587B1 (en) * 1997-12-23 2001-11-27 Microsoft Corporation Method, computer program product, and data structure for publishing a data object over a store and forward transport
US6662359B1 (en) * 2000-07-20 2003-12-09 International Business Machines Corporation System and method for injecting hooks into Java classes to handle exception and finalization processing
JP2002116917A (ja) * 2000-10-05 2002-04-19 Fujitsu Ltd オブジェクト指向型プログラミング言語によるソース・プログラムをコンパイルするコンパイラ
US7774750B2 (en) * 2005-07-19 2010-08-10 Microsoft Corporation Common concurrency runtime

Patent Citations (8)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JPH01297759A (ja) * 1988-05-26 1989-11-30 Tokyo Electric Power Co Inc:The ブロードキャストメモリ方式分散コンピュータシステム
JPH02132543A (ja) * 1988-11-12 1990-05-22 Nec Corp 情報処理装置
US5488723A (en) * 1992-05-25 1996-01-30 Cegelec Software system having replicated objects and using dynamic messaging, in particular for a monitoring/control installation of redundant architecture
WO1995008809A2 (en) * 1993-09-24 1995-03-30 Oracle Corporation Method and apparatus for data replication
US6625751B1 (en) * 1999-08-11 2003-09-23 Sun Microsystems, Inc. Software fault tolerant computer system
WO2002044835A2 (en) * 2000-11-28 2002-06-06 Gingerich Gregory L A method and system for software and hardware multiplicity
WO2003083614A2 (en) * 2002-03-25 2003-10-09 Eternal Systems, Inc. Transparent consistent active replication of multithreaded application programs
US20040073828A1 (en) * 2002-08-30 2004-04-15 Vladimir Bronstein Transparent variable state mirroring

Also Published As

Publication number Publication date
EP1763773A4 (en) 2008-12-17
IL178527A0 (en) 2007-02-11
EA009926B1 (ru) 2008-04-28
EP1763772A4 (en) 2008-12-17
EA200601942A1 (ru) 2007-04-27
EP1763774A1 (en) 2007-03-21
NZ550480A (en) 2010-02-26
EP1763774B1 (en) 2012-12-05
JP2007534065A (ja) 2007-11-22
WO2005103927A1 (en) 2005-11-03
EP1763772A1 (en) 2007-03-21
EP1763774A4 (en) 2008-12-03
WO2005103928A1 (en) 2005-11-03
MXPA06012209A (es) 2007-04-17
WO2005103924A1 (en) 2005-11-03
KR101209023B1 (ko) 2012-12-10
EP1763771A4 (en) 2008-12-17
CA2563900A1 (en) 2005-11-03
JP2007534063A (ja) 2007-11-22
IL178527A (en) 2011-11-30
CA2563900C (en) 2015-01-06
CN101908001B (zh) 2014-05-14
WO2005103925A1 (en) 2005-11-03
CN1965308B (zh) 2010-08-04
WO2005103926A1 (en) 2005-11-03
EP1763771A1 (en) 2007-03-21
BRPI0508929A (pt) 2007-08-14
EP1763773A1 (en) 2007-03-21
ZA200608766B (en) 2008-08-27
EP2341430A1 (en) 2011-07-06
CN1965308A (zh) 2007-05-16
JP2007534066A (ja) 2007-11-22
KR20070022253A (ko) 2007-02-26
CN101908001A (zh) 2010-12-08

Similar Documents

Publication Publication Date Title
US7844665B2 (en) Modified computer architecture having coordinated deletion of corresponding replicated memory locations among plural computers
CA2563900C (en) Modified computer architecture with coordinated objects
US20060020913A1 (en) Multiple computer architecture with synchronization
US20060095483A1 (en) Modified computer architecture with finalization of objects
US20050262513A1 (en) Modified computer architecture with initialization of objects
US20060265704A1 (en) Computer architecture and method of operation for multi-computer distributed processing with synchronization
AU2005236087B2 (en) Modified computer architecture with coordinated objects
AU2005236086A1 (en) Multiple computer architecture with synchronization
AU2005236088B2 (en) Modified computer architecture with finalization of objects
AU2005236085A1 (en) Modified computer architecture with initialization of objects
AU2005236089A1 (en) Multiple computer architecture with replicated memory fields
AU2006238334A1 (en) Modified computer architecture for a computer to operate in a multiple computer system

Legal Events

Date Code Title Description
A621 Written request for application examination

Free format text: JAPANESE INTERMEDIATE CODE: A621

Effective date: 20080404

A131 Notification of reasons for refusal

Free format text: JAPANESE INTERMEDIATE CODE: A131

Effective date: 20100921

A521 Request for written amendment filed

Free format text: JAPANESE INTERMEDIATE CODE: A523

Effective date: 20101221

A02 Decision of refusal

Free format text: JAPANESE INTERMEDIATE CODE: A02

Effective date: 20110131

A521 Request for written amendment filed

Free format text: JAPANESE INTERMEDIATE CODE: A523

Effective date: 20110531

A911 Transfer to examiner for re-examination before appeal (zenchi)

Free format text: JAPANESE INTERMEDIATE CODE: A911

Effective date: 20110606

A912 Re-examination (zenchi) completed and case transferred to appeal board

Free format text: JAPANESE INTERMEDIATE CODE: A912

Effective date: 20110701