
分散オブジェクト環境を学ぶ
連載:HORBと遊ぼう(3)
オブジェクト指向にシームレスな
分散オブジェクト環境
萩本順三
HORB Openマネージャ
株式会社豆蔵
2001/1/13
(1) HORBにおける継承とは |
「オブジェクト指向言語にシームレス」であることを一言でいうと「オブジェクト指向言語に一体化された技術(または環境)のように見える」ということでしょうか?
でもこれは難しいことです。そもそもオブジェクト指向って、何をもってオブジェクト指向かという定義もはっきりしないのですから(笑)。しかし対象の技術がオブジェクト指向をサポートしているというならば、次のような機能・メカニズムをサポートしているに違いありません。それ以外の技術は概念的にオブジェクト指向という考えをサポートしているんだと考える方が、頭がスッキリしますね。
(1)カプセル化(データ隠ぺい)
(2)クラス、インスタンス
(3)メッセージ通信(メソッド呼び出し)
(4)継承
(5)ポルモルフィズム(多態性)
前回までで、クラスでカプセル化されたリモート・オブジェクトを代理オブジェクト(Proxy)を通じて生成(new)し、メッセージ呼び出しをしました。よって、HORBは、(1)、(2)、(3)をサポートしているといえます。
では、残りの(4)継承と、(5)ポルモルフィズムはどうなっているのでしょうか?
もちろんHORBは両方サポートしています。だからオブジェクト指向言語にシームレスといわれるわけですが、その効力としてJava言語を理解できればHORBが超簡単に使えるようになるわけです。
HORBが簡単であるワケは、実はHORBは、この「オブジェクト指向言語にシームレス」な分散オブジェクト環境を追求してきたからこそなんです。
では、さっそくHORBがどんなふうに継承をサポートしているかについて、簡単なサンプルを使って見ていきます。その前に、まずはいつものようにスタンドアロンのJavaプログラミングから解説しましょう。
■クラスの継承利用
リスト1は、前回使用したTest2クラスです。リスト2(Test2Debug)は、Test2から継承して作成したクラスです。このクラスは、Test2を実行時に生成(new)するタイミングや、消去されるタイミングを観察するメソッドをTest2に追加することを目的としています。
今回のソースはここ(examples3.zip)からダウンロードしてください。
public class Test2{ |
リスト1 Test2.java
|
public class Test2Debug
extends Test2{ |
リスト2 Test2Debug.java
|
Test2から継承したTest2Debugには、継承を使ってTest2の属性(String name)とメソッド(setName、print)を引き継いでいます。よって、Test2Debugは、Test2のように使えます。さらに、Test2Debugは、コンストラクタ・メソッドとファナライザ・メソッド(finalize)を追加しています。
図1は、Test2クラスとTest2Debugクラスをクラス図というオブジェクト指向開発で使用する表記法で書いたものです。それぞれのクラスはそれぞれのクラスとして表現されています。
![]() |
図1 Test2とTest2Debug(クラス図) |
図2は、Test2インスタンスとTest2Debugインスタンスの内部構造をイメージした図です。この図から、Test2DebugはTest2の構造(メソッドと属性)を包含していることが分かるでしょう。
![]() |
図1 Test2とTest2Debug(インスタンスの内部構造) |
コンストラクタとは、クラス名と同じ名前を持つメソッド(Test2Debug)で、Test2Debugが生成(new)されるときに自動的に呼び出されます。つまりオブジェクトが生成されるときに必要となる初期処理をコンストラクタとして定義することができます。一方、ファナライザは、実行中に、どこからも参照されなくなったオブジェクトが、Javaのガーベッジ・コレクションによってメモリから解放される際に自動的に呼ばれるメソッドのことで、ソース中のように戻り値と引数がないメソッド(finalize)として定義します。
Test2Debugは、両者のメソッドを実装することで、オブジェクトの生成と消滅のタイミングを標準出力に表示する機能を持ったTest2の拡張クラスとなります。
Test2Debugを使ったJavaのスタンドアロンプログラムLocalInstanceTestをリスト3に示します。このソースの説明は、プログラムを動かした後の実行結果を見ながら行います。
001:public class LocalInstanceTest{ |
リスト3 LocalInstanceTest.java
|
○コンパイル
>javac Test2.java Test2Debug.java
LocalInstanceTest.java |
○実行結果
LocalInstanceTestの実行結果は次のようになります。では、この実行結果をLocalInstanceTestのソース(リスト3)と照らし合わせながら見ていきましょう。
まず、リスト3の3行目で、Test2型の5000個の配列を用意し、7行目でTest2Debugクラスのインスタンスを生成(new)しています。これを実行すると、インスタンス生成の際にコンストラクタ・メソッドが呼び出され、「[n]個目のインスタンスがnewされます」と5000個分が標準出力に表示されます(結果A)。
次に、12、13行目で、配列に入ったそれぞれのオブジェクトにメソッドを送ります。この2つのメソッドはTest2から継承されたものです(結果B)。
その後、19行目で、Test2Debugクラスのインスタンスを生成(new)し、同じ配列(test)に代入しています。これによって、Test2Debugのコンストラクタの出力結果が表示されます(結果C)。
この出力後、実行結果をよく観察していると、ある時点から「インスタンス[n]が消去されます」と表示されるようになると思います(結果D)。これは、21行目で生成されたインスタンスをtest配列のi番目に代入したため、前にその配列のi番目から参照されていたTest2Debugインスタンスがどこからも参照されないゴミとして登録され、JVMガーベッジ・コレクションのスレッドによってゴミとなったインスタンスがメモリから解放される契機でfinalizeメソッドが呼ばれているのです。どの段階で、インスタンスが生成され、どんなときにインスタンスが解放されるのか、この実行結果によって分かると思います(注1)。
また、Test2Debugクラスのように、継承を使えば、あるクラスを拡張することができるということもお分かりになったでしょう。
注1:JDKの環境によっては、本サンプルでfinalizeメソッドが呼ばれないケースもあるかもしれません。そのときには、リスト3の3行目の配列個数を増やしてみてください。例えば1万件といった数字にしてください。 >java LocalInstanceTest |
■HORBリモート・クラスの継承利用
HORBは、クラス継承が可能です。これはHORB特有の機能です。では、HORBでは、どのようにして継承を使うのでしょうか。
やり方は簡単です。Test2.java(リスト1)とTest2Debug.java(リスト2)は、そのままで結構です。LocalInstanceTestをRemoteInstanceTest(リスト4)と差し替えてください。
LocalInstanceTestからRemoteInstanceTestへの変更点は、8行目と20行目で生成(new)するオブジェクトのクラス名をTest2DebugからTest2Debug_Proxyに変更した部分となります。
こうすることで、サーバ側に存在するTest2Debugを、あたかもクライアントに存在しているかのように操作できます。
001:public class RemoteInstanceTest{ |
リスト4 RemoteInstanceTest.java
|
○コンパイル
Test2.javaとTest2Debug.javaをhorbcによってコンパイルします。例によってワーニングが出ますが、本例には関係ないことですので無視してください。
horbcの後、RemoteInstanceTest.javaをjavacによってコンパイルします。
>horbc -delete Test2.java
Test2Debug.java >javac RemoteInstanceTest.java |
○実行方法
まず、HORBサーバを立ち上げましょう。DOSコマンドプロンプトを開いて、horbを立ち上げてください。
>horb |
次は、クライアントの起動です。もう1つDOSコマンドプロンプトを開いて、次のように入力してください。もし、HORBサーバと異なるマシンでクライアントを立ち上げるならば、「localhost」の部分に、HORBサーバを立ち上げたマシンのホスト名を指定してください。
>java RemoteInstanceTest
localhost |
○実行結果
実行結果は、クライアントとHORBサーバの両方に出力されます。以下は、実行中の出力結果の一部を示したものです。この実行結果をじっくり観察してください。
クライアントで生成された代理オブジェクトTest2Debug_Proxyは、サーバ側に存在するTest2Debugの代理のオブジェクトとして完全に動作しています。これはまさに影武者のように完璧にTest2Debugを演じているといえませんか?
なぜなら、Test2Debug_Proxyは、Test2Debugの代理を演じる中で、次のようなことを実現しているからです。
- 継承を実現している
「Test2DebugのスーパークラスはTest2である」という実クラスの継承関係を「Test2Debug_ProxyのスーパークラスはTest2_Proxyである」という代理オブジェクトのクラス関係として忠実に再現している(図3参照)
![]() |
図3 オブジェクト(AddressBook)転送のイメージ図 |
- ポルモルフィズムを実現している
Test2Debug_ProxyクラスのインスタンスをTest2_Proxy変数に入れて操作ができる。これは、Test2DebugのインスタンスをTest2変数に入れて操作するということをリモート環境にて再現しているといえる
- オブジェクトの生成と消滅タイミング
代理オブジェクト(Test2Debug_Proxy)を生成(new)すると、実オブジェクトTest2Debugがサーバ側で生成(new)される。代理オブジェクト(Test2Debug_Proxy)の参照がなくなるとGC(ガーベッジ・コレクション)の対象となる。この時点で、サーバ側でも実オブジェクトがGCの対象となる
これらが示すことは、代理オブジェクトの実行時のライフサイクル(オブジェクトが生まれて消滅するまで)が実オブジェクトのライフサイクルと同等であるということです(若干の時間的なタイミングのずれはあります)。
[クライアント] >java RemoteInstanceTest
localhost |
[HORBサーバ]
>horb |
いかがですか、HORBの分散環境によって、継承を使った例を示しました。このほか、HORBは、インターフェイスの継承や、インターフェイス同士の継承などについてもサポートしています。
HORBの継承って結構いけそうでしょ。これがあるから、分散環境にて、クラス継承を使いたいと思ったときに簡単に使えてしまうので非常に便利なのです。
![]() |
(2)
HORBでオブジェクトが飛ぶ![]() |
Index | |
![]() |
(1) HORBにおける継承とは クラスの継承利用 HORBリモート・クラスの継承利用 |
(2) HORBでオブジェクトが飛ぶ オブジェクトがネットワーク間を渡り歩くとは? |
|
![]() |
連載記事一覧 |
- 実運用の障害対応時間比較に見る、ログ管理基盤の効果 (2017/5/9)
ログ基盤の構築方法や利用方法、実際の案件で使ったときの事例などを紹介する連載。今回は、実案件を事例とし、ログ管理基盤の有用性を、障害対応時間比較も交えて紹介 - Chatwork、LINE、Netflixが進めるリアクティブシステムとは何か (2017/4/27)
「リアクティブ」に関連する幾つかの用語について解説し、リアクティブシステムを実現するためのライブラリを紹介します - Fluentd+Elasticsearch+Kibanaで作るログ基盤の概要と構築方法 (2017/4/6)
ログ基盤を実現するFluentd+Elasticsearch+Kibanaについて、構築方法や利用方法、実際の案件で使ったときの事例などを紹介する連載。初回は、ログ基盤の構築、利用方法について - プログラミングとビルド、Androidアプリ開発、Javaの基礎知識 (2017/4/3)
初心者が、Java言語を使ったAndroidのスマホアプリ開発を通じてプログラミングとは何かを学ぶ連載。初回は、プログラミングとビルド、Androidアプリ開発、Javaに関する基礎知識を解説する。
![]() |
|
|
|
![]() |