(57)【特許請求の範囲】
【請求項１】
仮想マシン上で実行されるプログラムに含まれる複数の機能の実行を制御する処理をコンピュータのプロセッサに実行させるための制御プログラムであって、
前記複数の機能のうちスレッドとして実行される第１の機能の実行開始時における、前記仮想マシンに割り当てられたメモリの残量を、実行中の機能のスレッドに関するデータを格納する実行中スレッドテーブルから読み出すステップと、
前記仮想マシンから、前記第１の機能の実行終了時における、前記仮想マシンに割り当てられたメモリの残量を取得するステップと、
前記第１の機能の実行開始時におけるメモリの残量と前記第１の機能の実行終了時におけるメモリの残量との差である第１のメモリ消費量を算出するステップと、
過去に実行された各前記機能の目安のメモリ消費量である第２のメモリ消費量を実行毎に格納する第１のメモリ消費量テーブル又は過去に実行された各前記機能の前記第２のメモリ消費量の平均値を格納する第２のメモリ消費量テーブルを用いて、前記第１の機能と、前記実行中スレッドテーブルから特定される、前記第１の機能と同時実行されている他の機能とについて、前記第２のメモリ消費量の平均値を取得するステップと、
算出された前記第１のメモリ消費量を、前記第１の機能についての前記第２のメモリ消費量の平均値と前記第１の機能と同時実行されている他の機能についての前記第２のメモリ消費量の平均値とを基に按分することにより、前記第１の機能についての前記第２のメモリ消費量を算出する第１算出ステップと、
を実行させるための制御プログラム。
【請求項２】
前記仮想マシンから、前記複数の機能のうちスレッドとして実行される第２の機能の実行開始時における、前記仮想マシンに割り当てられたメモリの残量を取得するステップと、
前記第１のメモリ消費量テーブルから、前記第２の機能についての前記第２のメモリ消費量を抽出し、当該第２のメモリ消費量から前記第２の機能のメモリ消費の予測値を算出する第２算出ステップと、
前記第２の機能の実行開始時におけるメモリの残量と前記予測値との差が予め定められた閾値未満である場合に、前記第２の機能のスレッドを前記仮想マシンに停止させるステップと、
をさらに前記プロセッサに実行させるための請求項１記載の制御プログラム。
【請求項３】
前記第２算出ステップが、
抽出された前記第２のメモリ消費量の平均値を算出するステップと、
抽出された前記第２のメモリ消費量と前記第２のメモリ消費量の平均値との差の絶対値の平均値を算出し、当該平均値に所定割合を乗じた値である分散リスク値を算出するステップと、
前記第２のメモリ消費量の平均値と前記分散リスク値との和である前記予測値を算出するステップと、
を含む請求項２記載の制御プログラム。
【請求項４】
前記第１算出ステップが、
前記第１の機能の前記第２のメモリ消費量の平均値と、前記第１の機能と同時に実行されている他の機能の前記第２のメモリ消費量の平均値に所定割合を乗じた値とで、前記第１のメモリ消費量を按分して、前記第１の機能の前記第２のメモリ消費量を算出するステップ
を含む請求項１記載の制御プログラム。
【請求項５】
前記第２算出ステップが、
前記第１のメモリ消費量テーブルから、前記第２の機能についての前記第２のメモリ消費量を所定実行数分抽出できたか判断するステップ
を含み、
前記第２のメモリ消費量を所定実行数分抽出できない場合には、前記第２の機能の実行開始時におけるメモリの残量を含む、前記第２の機能のスレッドに関するデータを、前記実行中スレッドテーブルに登録するステップ
をさらに実行させるための請求項２記載の制御プログラム。
【請求項６】
仮想マシン上で実行されるプログラムに含まれる複数の機能の実行を制御する制御部を有するコンピュータにより実行される制御方法であって、
前記制御部が、前記複数の機能のうちスレッドとして実行される第１の機能の実行開始時における、前記仮想マシンに割り当てられたメモリの残量を、実行中の機能のスレッドに関するデータを格納する実行中スレッドテーブルから読み出すステップと、
前記制御部が、前記仮想マシンから、前記第１の機能の実行終了時における、前記仮想マシンに割り当てられたメモリの残量を取得するステップと、
前記制御部が、前記第１の機能の実行開始時におけるメモリの残量と前記第１の機能の実行終了時におけるメモリの残量との差である第１のメモリ消費量を算出するステップと、
前記制御部が、過去に実行された各前記機能の目安のメモリ消費量である第２のメモリ消費量を実行毎に格納する第１のメモリ消費量テーブル又は過去に実行された各前記機能の前記第２のメモリ消費量の平均値を格納する第２のメモリ消費量テーブルを用いて、前記第１の機能と、前記実行中スレッドテーブルから特定される、前記第１の機能と同時実行されている他の機能とについて、前記第２のメモリ消費量の平均値を取得するステップと、
前記制御部が、算出された前記第１のメモリ消費量を、前記第１の機能についての前記第２のメモリ消費量の平均値と前記第１の機能と同時実行されている他の機能についての前記第２のメモリ消費量の平均値とを基に按分することにより、前記第１の機能についての前記第２のメモリ消費量を算出するステップと、
を含む制御方法。
【請求項７】
仮想マシン上で実行されるプログラムに含まれる複数の機能の実行を制御する制御部を有し、
前記制御部が、
前記複数の機能のうちスレッドとして実行される第１の機能の実行開始時における、前記仮想マシンに割り当てられたメモリの残量を、実行中の機能のスレッドに関するデータを格納する実行中スレッドテーブルから読み出す手段と、
前記仮想マシンから、前記第１の機能の実行終了時における、前記仮想マシンに割り当てられたメモリの残量を取得する手段と、
前記第１の機能の実行開始時におけるメモリの残量と前記第１の機能の実行終了時におけるメモリの残量との差である第１のメモリ消費量を算出する手段と、
過去に実行された各前記機能の目安のメモリ消費量である第２のメモリ消費量を実行毎に格納する第１のメモリ消費量テーブル又は過去に実行された各前記機能の前記第２のメモリ消費量の平均値を格納する第２のメモリ消費量テーブルを用いて、前記第１の機能と、前記実行中スレッドテーブルから特定される、前記第１の機能と同時実行されている他の機能とについて、前記第２のメモリ消費量の平均値を取得する手段と、
算出された前記第１のメモリ消費量を、前記第１の機能についての前記第２のメモリ消費量の平均値と前記第１の機能と同時実行されている他の機能についての前記第２のメモリ消費量の平均値とを基に按分することにより、前記第１の機能についての前記第２のメモリ消費量を算出する手段と、
を有するコンピュータ。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される複数の機能の実行を制御する技術に関する。
【背景技術】
【０００２】
仮想マシン上で動作する言語処理系（Ｊａｖａ（登録商標）や．ＮＥＴ）が一般的になり、メモリ取得、解放が自動化され、開発容易性、メモリリーク防止に効果を発揮している。一方、アプリケーション側が仮想マシンが管理するメモリ領域を制御するＡＰＩ（Application Program Interface）セットは存在せず、運用中にメモリ消費に関する問題が発生しても、原因を特定し、同時実行制御、機能改善などを実施する体系的な方法は存在していない。
【０００３】
開発中であれば、プロファイラなどの既存製品を使用して単一機能毎にメモリ消費量を測定し、原因を特定することは可能であるが、実際の運用中では複数機能が同時並行で実行されるためメモリ消費量を特定することは不可能である。また、プロファイラのようにオーバーヘッドの大きい機能を実際の運用中に使用することは現実的ではない。
【０００４】
また、特開２００６−２８５８７１号公報には、情報処理装置がメモリ不足でアプリケーションを起動できないエラーになる可能性を小さくし、新たなアプリケーションの起動やインストールができなくなるといった不都合を回避するための技術が開示されている。具体的には、複数のアプリケーションが使用するメモリ量を管理する情報処理装置は、アプリケーション毎の最大メモリ使用量を取得する取得手段と、取得手段により取得したアプリケーション毎の最大メモリ使用量の和を算出する算出手段と、アプリケーションの起動要求時に、算出手段により算出したアプリケーション毎の最大メモリ使用量の和が許容量を超えたか否かに基づいて、アプリケーションの起動の可否を判断する制御手段とを備える。
【特許文献１】特開２００６−２８５８７１号公報
【発明の開示】
【発明が解決しようとする課題】
【０００５】
図１にＯＳ（Operating System）のメモリ管理を模式的に示す。ＯＳは、ＯＳ上で実行されるアプリケーションなどのプロセス（仮想マシンの場合も含む）毎に、ＯＳが管理するメモリ領域において専用のメモリ領域を割り当てる。図１の例では、プロセス１乃至ｎが存在しており、それぞれにプロセス１専用メモリ領域、プロセス２専用メモリ領域、．．．プロセスｎ専用メモリ領域が確保される。このように、プロセス毎に専用のメモリ領域が割り当てられるので、当該メモリ領域のサイズが特定できれば、ＯＳが残余のメモリ容量を特定することも容易である。上記公報も、このような前提の下で述べられている。
【０００６】
しかしながら、ＯＳ上の仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される各機能については、図１に示したＯＳの場合とは異なり、簡単にメモリ消費量を特定できない。具体的には、仮想マシンは、ＯＳから割り当てられたメモリ領域を各スレッドが使用できるように提供するが、各スレッド専用のスタック領域とは別に、共有メモリ領域（ヒープ領域）を提供する。各スレッドは、この共有メモリ領域を必要なときに必要なだけ使用する。図２の例では、スレッド３は単独で共有データＢを使用しているが、共有データＡについては、スレッド１及び２で共有しており、スレッド２は、共有データＡ及びＣを使用している。このように、１つのスレッドが使用しているメモリ容量を完全には分別して特定できない。
【０００７】
より具体的に、図３（ａ）に示す第１のスレッドと、図３（ｂ）に示す第２のスレッドとが同時に実行される場合を想定する。ここで、第１のスレッドの開始時（ＭＡ−１）と第２のスレッドの開始時（ＭＢ−１）とにおけるメモリ残量（仮想マシンが管理するメモリ領域のメモリ残量）が「１００００」であり、第１のスレッドの終了時（ＭＡ−２）と第２のスレッドの終了時（ＭＢ−２）とにおけるメモリ残量が「８９５０」であるものとする。これらのメモリ残量については、仮想マシンから取得できる。一方、実際には、第１のスレッドのＡ−１乃至Ａ−３でのメモリ消費量が、「１００」「２００」「３００」でトータル「６００」あり、第２のスレッドのＢ−１乃至Ｂ−３でのメモリ消費量が「２５０」「５０」「１５０」でトータル「４５０」であった場合にも、ＯＳや仮想マシンを改変することなく上記のようなメモリ残量しか特定できない場合には、第１のスレッドのメモリ消費量も第２のスレッドのメモリ消費量も「１００００」−「８９５０」＝「１０５０」としか計算できない。
【０００８】
このように、従来においては、仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される各機能のメモリ消費量を特定するという着想自体が存在せず、また目安となる妥当な値さえも算出することができなかった。従って、新たにスレッドを実行する際に、当該スレッドを実行して問題がないのか否かについても適切に判断できなかった。また、ＯＳや仮想マシンを改変することができれば、可能かもしれないが、改変には大きな手間が掛かり、汎用的なＯＳや仮想マシンを使用することが多い現状においては現実的ではない。
【０００９】
従って、本発明の目的は、ＯＳや仮想マシンを改変することなく、仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される各機能の実行を適切に制御するための技術を提供することである。
【００１０】
また、本発明の他の目的は、ＯＳや仮想マシンを改変することなく、仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される各機能のメモリ消費量の適切な目安を与えることができるようにするための技術を提供することである。
【課題を解決するための手段】
【００１１】
本発明に係る制御プログラムは、仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される複数の機能の実行を制御する制御プログラムであって、コンピュータのプロセッサに、仮想マシンから、特定の機能の実行開始時における、当該仮想マシンに割り当てられたメモリの残量を取得するステップと、過去に実行された各機能の目安メモリ消費量を実行毎に格納する機能別メモリ消費量テーブルから、特定の機能についての目安メモリ消費量を抽出し、抽出された目安メモリ消費量から特定の機能のメモリ消費予測値を算出するメモリ消費予測値算出ステップと、メモリの残量とメモリ消費予測値との差が予め定められた閾値未満である場合に、特定の機能のスレッドを仮想マシンに停止させるステップとを実行させる。
【００１２】
ＯＳや仮想マシンとは別の制御プログラムにより、特定の機能のメモリ消費予測値を算出して、メモリの残量と上記メモリ消費予測値との差に基づき適切に特定の機能の実行制御を行うことができるようになる。
【００１３】
なお、上記制御プログラムは、メモリの残量とメモリ消費予測値との差が予め定められた閾値以上である場合には、メモリの残量を含む、特定の機能のスレッドに関するデータを、実行中の機能のスレッドに関するデータを格納する実行中スレッドテーブルに登録するステップと、仮想マシンから、特定の機能の実行終了時における、仮想マシンに割り当てられたメモリの残量である当該メモリの第２の残量を取得するステップと、実行中スレッドテーブルから特定の機能のメモリの残量を取得するステップと、メモリの第２の残量とメモリの残量との差である純メモリ消費量を、特定の機能と、実行中スレッドテーブルから特定される、特定の機能と同時実行されている他の機能とで按分して、特定の機能についての目安メモリ消費量を算出する目安メモリ消費量算出ステップと、特定の機能についての目安メモリ消費量を機能別メモリ消費量テーブルに登録するステップとをさらに実行させる。
【００１４】
このように特定の機能の目安メモリ消費量を算出することができるので、例えば、機能別メモリ消費量テーブルを解析して、問題のある機能を抽出して、改善などを行うことができるようになる。
【００１５】
さらに、上で述べたメモリ消費予測値算出ステップが、抽出された目安メモリ消費量の平均値を算出するステップと、抽出された目安メモリ消費量と目安メモリ消費量の平均値との差の絶対値の平均値の所定割合を分散リスク値として算出するステップと、目安メモリ消費量の平均値と分散リスク値との和をメモリ消費予測値として算出するステップとを含むようにしてもよい。分散リスク値を加算することなく、その分閾値を調整するような構成も可能である。
【００１６】
また、上で述べた目安メモリ消費量算出ステップが、特定の機能の目安メモリ消費量の平均値を取得（例えば機能別メモリ消費量テーブルから計算する場合もあれば、キャッシュに保持しているデータを読み出す場合もある）するステップと、実行中スレッドテーブルから特定される、特定の機能と同時実行されている他の機能の各々について、目安メモリ消費量の平均値を取得（例えば機能別メモリ消費量テーブルから計算する場合もあれば、キャッシュに保持しているデータを読み出す場合もある）するステップと、特定の機能の目安メモリ消費量の平均値と、他の機能の各々の目安メモリ消費量の平均値の所定割合とで、純メモリ消費量を按分して、特定の機能の目安メモリ消費量を算出するステップとを含むようにしてもよい。所定割合は、例えば同時実行スレッドの同時実行度合いに応じて設定される。
【００１７】
さらに、上で述べたメモリ消費予測値算出ステップが、過去に実行された各機能の目安メモリ消費量を実行毎に格納する機能別メモリ消費量テーブルから、特定の機能についての目安メモリ消費量を所定実行数分抽出できたか判断するステップを含むようにしてもよい。そして、目安メモリ消費量を所定実行数分抽出できない場合には、メモリの残量を含む、特定の機能のスレッドに関するデータを、実行中の機能のスレッドに関するデータを格納する実行中スレッドテーブルに登録するステップをさらに実行させるようにしてもよい。機能別メモリ消費量テーブルにデータが十分蓄積されていない場合の処理を規定するものである。
【００１８】
なお、本プログラムは、例えばフレキシブルディスク、ＣＤ−ＲＯＭ、光磁気ディスク、半導体メモリ、ハードディスク等の記憶媒体又は記憶装置に格納される。また、ネットワークなどを介してデジタル信号として配信される場合もある。尚、中間的な処理結果はメインメモリ等の記憶装置に一時保管される。
【発明の効果】
【００１９】
本発明によれば、ＯＳや仮想マシンを改変することなく、仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される各機能の実行を適切に制御することができるようになる。
【００２０】
また、本発明の他の側面によれば、ＯＳや仮想マシンを改変することなく、仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される各機能のメモリ消費量の適切な目安を与えることができるようになる。
【発明を実施するための最良の形態】
【００２１】
図４に、本発明の一実施の形態に係るプログラム構成を示す。図４に示すように、ＯＳ１上、１つのプロセスとして仮想マシン１０が実行される。ＯＳ１は、仮想マシン１０に専用のメモリ領域を割り当て、仮想マシン１０はその専用メモリ領域を利用して実行される。また、仮想マシン１０上、様々なスレッドが起動される。例えば、リクエストの受け付け、実行すべき機能の判定、実行機能の呼び出しなどを実施するサーバ・プログラム１１と、例えばサーバ・プログラム１１によって呼び出され且つメモリ消費量の測定対象及びスレッド起動の制御対象となる測定対象プログラム１２とが仮想マシン１０上スレッドとして実行される。さらに、測定対象プログラム１２から呼び出され且つ本実施の形態における主要な処理を実施するメモリ管理モジュール１４や、測定対象プログラム１２によって利用される各種ライブラリ１３も、仮想マシン１０上で実行される。なお、測定対象プログラム１２には、以下で述べるように、コンパイル時にメモリ管理モジュール１４を呼び出すコードが自動的に追加され、呼び出されたメモリ管理モジュール１４によって実行制御が行われるようになる。メモリ管理モジュール１４は、機能別メモリ消費量テーブル１４１及び実行中スレッドテーブル１４２を用いて処理を実施する。また、機能別平均メモリ消費量テーブル１４３を用いる場合もある。
【００２２】
図５に、機能別メモリ消費量テーブル１４１の一例を示す。測定対象プログラム１２の、スレッドとして実行される、予め定められた機能が実行される毎に、１レコードが生成され、図５の例では、各レコードにつき、通番、機能ＩＤ（例えば、Ｊａｖａ（登録商標）の場合には、パッケージ名．クラス名＃メソッド名、Ｃ＃の場合には、ネームスペース名．クラス名＃メソッド名といった関数又はサブルーチンを一意に表す名前）、時刻、目安メモリ消費量を登録するようになっている。
【００２３】
図６に、実行中スレッドテーブル１４２の一例を示す。実行中スレッドテーブル１４２には、現在実行中のスレッドが列挙されるようになっており、図６の例では、実行中の各スレッドにつき、スレッドＩＤ、機能ＩＤ、開始時点メモリ残量、同時実行機能名とが登録されるようになっている。
【００２４】
図７に、機能別平均メモリ消費量テーブル１４３の一例を示す。本テーブルについては使用しない方法もあるが、使用すれば処理が高速化される。機能別平均メモリ消費量テーブル１４３には、１つの機能につき１つのレコードが登録されるようになっており、機能ＩＤと、平均メモリ消費量（以下で詳細に説明する）と、最終更新時刻とを登録するようになっている。なお、最終更新時刻が、所定の基準より古いレコードについては、そのレコードを用いることなく、別途平均メモリ消費量を算出することが好ましい。
【００２５】
なお、仮想マシン上で動作するプログラム（例えばサーバ・プログラム１１等）は、仮想マシン１０に対して以下のような事項を命じることができる。
・プログラムは、仮想マシン１０に命令することで、スレッドを生成、消滅させることができる。
・プログラムは、仮想マシン１０に命令することで、実行中のスレッドを停止させることや、停止中のスレッドを再実行させることができる。
・プログラムは、仮想マシン１０に命令して、メモリ領域を使用する（メモリ領域にデータを置く）ことができる。
・プログラムは、仮想マシン１０に問い合わせることで、「メモリ領域のトータル」と「メモリ領域の使用量」を知ることができる。すなわち、メモリ残量を把握することができる。
・プログラムは、仮想マシン１０に命令して、現在自スレッドが実行しているプログラムの手順を、他スレッドが実行しようとしたときに開始を待たせる（排他制御を行う）ことができる。
【００２６】
次に、図４に示したプログラム構成の詳細を図８を用いて説明する。サーバ・プログラム１１は、リクエストの受け付け、実行すべき機能を判定し、実行すべき機能の呼び出しを行う。図８の例では、機能ＩＤ：com.fuji.xxx.XClass#FunctionAという機能２１と、機能ＩＤ：com.fuji.xxx.XClass#FunctionBという機能２２とを、リクエストに応じて呼び出す。どの関数やサブルーチンを機能と定義するかは任意であって、メモリ消費量を測定したい単位又はスレッドの起動を制御するのに適切な単位で設定することが好ましい。但し、実際には、アプリケーションの開発においては、一定のルールに従ってクラス名やメソッド名を付与するので、当該ルールに従って機能を定義することも可能である。
【００２７】
機能２１は、機能開始処理部２１１、本来の処理部２１２及び機能終了処理部２１３を含む。機能開始処理部２１１及び機能終了処理部２１３は、本実施の形態において、例えば本来の処理部２１２に対してアスペクト指向技術等によって自動的に埋め込まれる部分であり、メモリ管理モジュール１４を呼び出す。本来の処理部２１２は、機能２１の本来の処理を行う部分である。必要に応じて、共通処理モジュール２３を呼び出す場合もある。
【００２８】
同様に、機能２２は、機能開始処理部２２１、本来の処理部２２２及び機能終了処理部２２３を含む。機能開始処理部２２１及び機能終了処理部２２３は、本実施の形態において、例えば本来の処理部２２２に対してアスペクト指向技術等によって自動的に埋め込まれる部分であり、メモリ管理モジュール１４を呼び出す。本来の処理部２２２は、機能２２の本来の処理を行う部分である。必要に応じて、共通処理モジュール２３を呼び出す場合もある。
【００２９】
次に、図８に示したプログラムの処理の概要を図９を用いて説明する。まず、スレッド１で、サーバ・プログラム１１の実行が開始され、例えばエンドユーザからの機能実行リクエストの待ち受け状態となり、停止する（サーバ・プログラム手順１）。ここで、エンドユーザから機能実行リクエストを受け取ると、サーバ・プログラム１１は処理を再開し、機能判定処理を実施する（サーバ・プログラム手順２）。実行すべき機能が特定されると、並列処理のため仮想マシン１０に対して新たなスレッド２を生成させ、実行すべき機能の実行を行わせる（サーバ・プログラム手順３）。その後、スレッド１では、サーバ・プログラム手順１に戻る。なお、スレッド２における機能の実行が終了すると、サーバ・プログラム１１においても終了処理を実施する場合もあるが、ここでは本実施の形態の主旨とははずれるため、説明を省略する。
【００３０】
サーバ・プログラム１１の命令によって仮想マシン１０によって生成されるスレッド２では、例えば機能２１が実行されるものとする。機能２１では、最初に機能開始処理部２１１における、メモリ管理モジュール１４の呼び出しコードが実行され、メモリ管理モジュール１４の機能開始処理が実行される（プログラム手順Ｍ−１）。このメモリ管理モジュール１４の機能開始処理については後に詳述する。このメモリ管理モジュール１４の機能開始処理が終了すると、本来の処理部２１２による処理（手順Ａ−１乃至Ａ−４）を実行する。なお、図８に示したように、必要に応じて共通処理モジュール２３を呼び出すようにしても良い。
【００３１】
そして、本来の処理部２１２の処理が完了すると、機能２１の機能終了処理部２１３におけるメモリ管理モジュール１４の呼び出しコードが実行され、メモリ管理モジュール１４の機能終了処理が実行される（プログラム手順Ｍ−２）。このメモリ管理モジュール１４の機能終了処理については後に詳述する。そして、スレッド２の実行を終了させ、仮想マシン１０によりスレッド２を消滅させる。
【００３２】
以下、図１０乃至図１６を用いて、メモリ管理モジュール１４の機能開始処理について詳しく述べる。最初に、メモリ管理モジュール１４は、他スレッド排他命令を仮想マシン１０に出力する（ステップＳ１）。これによって、他のスレッドにおいてメモリ管理モジュール１４を呼び出したとしても、他スレッド排他解除命令が出されるまで、本スレッド以外では、メモリ管理モジュール１４の機能開始処理は実行されない。
【００３３】
次に、メモリ管理モジュール１４は、メモリ残量を仮想マシン１０から取得する（ステップＳ３）。仮想マシン１０の既存機能を利用するものである。そして、メモリ管理モジュール１４は、機能別メモリ消費予測値算出処理を実施する（ステップＳ５）。この機能別メモリ消費予測値算出処理については、図１１乃至図１６を用いて説明する。
【００３４】
まず、メモリ管理モジュール１４は、機能別メモリ消費量テーブル１４１を、本機能ＩＤ及び予測対象期間により検索し、該当レコードを抽出する（ステップＳ２１）。機能ＩＤについては、例えばメモリ管理モジュール１４を呼び出した際に、機能２１の機能開始処理部２１１から取得するようにする。また、予測対象期間は、図１２に示すようなメモリ管理モジュール１４の設定パラメータのうちの１つであり、例えば一週間（＝６０４８００秒）といった数値が設定される。ステップＳ２１で抽出されるレコードの一例を、図１３に示す。ここでは８レコードが抽出されたものとする。
【００３５】
そして、メモリ管理モジュール１４は、停止判定閾値以上のレコードが抽出されたか判断する（ステップＳ２３）。停止判定閾値は、図１２に示すようなメモリ管理モジュール１４の設定パラメータのうちの１つであり、例えば「５」といった数値が設定される。停止判定閾値以上のレコードが抽出されていない場合には、件数が少なく予測精度が低いので、スレッド停止不要として設定し、元の処理に戻る（ステップＳ２５）。
【００３６】
一方、停止判定閾値以上のレコードが抽出できた場合には、メモリ管理モジュール１４は、抽出レコードからメモリ消費量平均値を算出し、所定のメモリ領域に格納する（ステップＳ２７）。図１３の例では、停止判定閾値が「５」で抽出レコード数が「８」であるから、メモリ消費量の平均値を算出する。図１３の例では、メモリ消費量平均値は「９７５０」と算出される。なお、本ステップにおいて算出されたメモリ消費量平均値については、機能別平均メモリ消費量テーブル１４３に登録して、後に用いるようにしても良い。
【００３７】
また、メモリ管理モジュール１４は、抽出レコードにおける各メモリ消費量の上記メモリ消費量平均値からの差の絶対値の平均を算出し、所定のメモリ領域に格納する（ステップＳ２９）。図１３の例では、メモリ消費量平均値からの差の絶対値は、上から順に「２２５０」「２７５０」「２５０」「７５０」「２５０」「１２５０」「１７５０」「１２５０」となる。従って、この平均は、「１３１２．５」と算出される。
【００３８】
そして、メモリ管理モジュール１４は、差の絶対値の平均と分散許容値との積によって分散リスク値を算出し、所定のメモリ領域に格納する（ステップＳ３１）。分散許容値は、図１２に示すようなメモリ管理モジュール１４の設定パラメータのうちの１つであり、例えば「０．８」といった数値が設定される。分散リスク値は、メモリ消費量平均値からのマージンに相当する。図１３の例では、１３１２．５×０．８＝１０５０が分散リスク値として算出される。その後、メモリ管理モジュール１４は、メモリ消費量平均値と分散リスク値との和により機能別メモリ消費予測値を算出し、所定のメモリ領域に格納する（ステップＳ３３）。図１３の例では、機能別メモリ消費予測値は９７５０＋１０５０＝１０８００と算出される。そして元の処理に戻る。
【００３９】
図１０の説明に戻って、メモリ管理モジュール１４は、本スレッド（スレッド２）の停止が必要であるか判断する（ステップＳ７）。本ステップでは、ステップＳ２５でスレッド停止不要が設定されていれば、スレッド停止不要と判断し、それ以外の場合には、ステップＳ３で取得したメモリ残量とステップＳ３３で算出された機能別メモリ消費予測値との差が、メモリ残量許容量より小さいか判断し、小さい場合には、メモリ不足が予測されるので、スレッド停止が必要と判断する。一方、メモリ残量と機能別メモリ消費予測値との差がメモリ残量許容量以上である場合には、スレッド停止は不要と判断する。メモリ残量許容量は、図１２に示すようなメモリ管理モジュール１４の設定パラメータの１つであり、例えば「１０００」といった数値が設定される。例えば、メモリ残量が「２００００」であったとすると、図１３の例では、「２００００」−「１０８００」＝「９２００」であり、メモリ残量許容量より多いので、スレッドの停止は不要と判断される。
【００４０】
なお、ステップＳ７でスレッド停止が必要と判断された場合には、メモリ管理モジュール１４は、他スレッド排他解除命令及び本スレッド（スレッド２）の停止命令を仮想マシン１０に出力する（ステップＳ９）。そしてステップＳ１に戻る。これにより、仮想マシン１０は、メモリ管理モジュール１４の排他状態を解除して、他スレッドによる実行を許可するようになる。さらに、スレッド２の実行を停止させる。
【００４１】
一方、スレッド停止が不要と判断された場合には、メモリ管理モジュール１４は、実行中スレッドテーブル１４２の全レコードの同時実行機能に、本機能ＩＤを追加登録する（ステップＳ１１）。例えばステップＳ１１実行前に図１４のような実行中スレッドテーブル１４２が存在している場合には、ステップＳ１１実行によって図１５に示すような実行中スレッドテーブルに変化する。すなわち、スレッド２で実行中の機能がＦｕｎｃＡ（又はＦｕｎｃｔｉｏｎＡ）だとすると、ＦｕｎｃＡが、実行中スレッドテーブルの各レコードの同時実行機能名の列に追加登録される（太字）。
【００４２】
さらに、メモリ管理モジュール１４は、実行中スレッドテーブル１４２に、本スレッドについてのデータを登録する（ステップＳ１３）。すなわち、図１６に示すような状態となる。具体的には、３行目のスレッドＩＤ「３」、機能ＩＤ「ＦｕｎｃＡ」、開始時点メモリ残量「２００００」、同時実行機能「ＦｕｎｃＸ，ＦｕｎｃＹ」が登録される（太字）。なお、同時実行機能の列については、既に登録済みの第１及び第２行目の機能ＩＤが登録される。
【００４３】
そして、メモリ管理モジュール１４は、仮想スレッド排他解除命令を仮想マシン１０に出力する（ステップＳ１５）。これによって、他のスレッドにおいてメモリ管理モジュール１４を呼び出すことができるようになる。そして、機能２１の本来の処理を実行する。
【００４４】
以上のような処理を実施することによって、十分メモリに余裕があると判断された場合にはスレッドの実行を継続し、メモリ不足が予測される場合にはスレッドの実行を停止させて、システム全体の稼働を安定化させることができるようになる。
【００４５】
なお、本実施の形態では、機能別メモリ消費予測値を算出する際に、分散リスク値を算出してメモリ消費量平均値に加算する方法を採用しているが、簡易的には分散リスク値を採用せずメモリ残量許容値に適当なメモリ容量を上乗せして判断するような方法でも可能である。さらに、設定パラメータは、実行環境に応じて適切に設定する必要があり、図１２の例は一例である。
【００４６】
次に、メモリ管理モジュール１４の機能終了処理について図１７乃至図２０を用いて説明する。メモリ管理モジュール１４は、他スレッド排他命令を仮想マシン１０に出力する（ステップＳ４１）。ステップＳ１と同様である。そして、メモリ管理モジュール１４は、実行中スレッドテーブル１４２から本機能の開始時点メモリ残量を読み出す（ステップＳ４３）。図１６のような実行中スレッドテーブル１４２であれば、３行目から開始時点メモリ残量の「２００００」というデータを読み出す。
【００４７】
そして、メモリ管理モジュール１４は、現時点におけるメモリ残量を仮想マシン１０から終了時点メモリ残量として取得する（ステップＳ４５）。例えば、ここでは「４０００」というデータが取得されたものとする。本実施の形態では、様々な機能によって仮想マシン１０に割り当てられたメモリは消費されていって、メモリ残量が減少することを前提としている。しかし、仮想マシン１０に含まれるメモリ管理部によってガベージコレクションが行われて、メモリ残量が増加する場合もある。そのような場合には、以下の処理で目安メモリ消費量を算出することはできないので、そのような場合にはステップＳ５１に移行する。
【００４８】
そして、メモリ管理モジュール１４は、目安メモリ消費量計算処理を実施する（ステップＳ４７）。目安メモリ消費量計算処理については図１８を用いて説明する。まず、メモリ管理モジュール１４は、開始時点メモリ残量から終了時点メモリ残量を差し引き、純メモリ消費量を算出し、所定のメモリ領域に格納する（ステップＳ６１）。上の例では「２００００」−「４０００」＝「１６０００」と計算される。但し、純メモリ消費量は、他の機能が消費した分を含む。
【００４９】
次に、メモリ管理モジュール１４は、実行中スレッドテーブル１４２から全同時実行機能を特定する（ステップＳ６３）。このスレッドで実行中の機能を含め、全ての同時実行機能を特定する。図１５の例では３つの機能（ＦｕｎｃＸ、ＦｕｎｃＹ及びＦｕｎｃＡ）が特定される。そして、全同時実行機能ＩＤのうち未処理のものを１つ特定する（ステップＳ６５）。さらに、機能別メモリ消費量テーブル１４１を、特定された機能ＩＤ及び予測対象期間（図１２）で検索し、該当するレコードを特定する（ステップＳ６７）。ステップＳ２１と同様の処理を行う。そして、メモリ管理モジュール１４は、停止判定閾値（図１２）以上のレコードが抽出できたか判断する（ステップＳ６９）。停止判定閾値以上のレコードが抽出できない場合には、メモリ消費量平均値を算出するのに不適切であるものとして、全同時実行機能のメモリ消費量を同一の値として、純メモリ消費量を按分することによって、目安メモリ消費量を算出する（ステップＳ７１）。そして、元の処理に移行する。
【００５０】
一方、停止判定閾値以上のレコードが抽出できた場合には、メモリ管理モジュール１４は、抽出されたレコードにおけるメモリ消費量を平均することによって、メモリ消費量平均値を算出し、所定のメモリ領域に格納する（ステップＳ７３）。
【００５１】
そして、メモリ管理モジュール１４は、全同時実行機能について処理を行ったか判断する（ステップＳ７５）。未処理の機能が存在する場合には、ステップＳ６５に戻る。
【００５２】
このようにして、上で述べた例では、ＦｕｎｃＸのメモリ消費量平均値（例えば「５０００」）、ＦｕｎｃＹのメモリ消費量平均値（例えば「６０００」）及びＦｕｎｃＡのメモリ消費量平均値（例えば「９７５０」）が算出される。なお、機能別平均メモリ消費量テーブル１４３を用いる場合には、所定時間以内の計算結果（すなわちメモリ消費量平均値）が格納されているかをステップＳ６５の後に確認し、所定時間以内の計算結果が存在する場合にはステップＳ６７乃至Ｓ７３をスキップし、所定時間以内の計算結果が存在しない場合には上で述べたステップＳ６７乃至Ｓ７３を実行するようにしても良い。また、ステップＳ６７乃至Ｓ７３を実行した場合には、計算されたメモリ消費量平均値を、機能別平均メモリ消費量テーブル１４３に登録しておく。
【００５３】
全同時実行機能について処理が完了した場合には、メモリ管理モジュール１４は、純メモリ消費量を全同時実行機能のメモリ消費量平均値を用いて仮想的に按分することによって、目安メモリ消費量を算出し、所定のメモリ領域に格納する（ステップＳ７７）。具体的には、純メモリ消費量（１６０００）×本機能のメモリ消費量平均値（９７５０）／（本機能のメモリ消費量平均値（９７５０）＋（第１の同時実行機能（ＦｕｎｃＸ）のメモリ消費量平均値（５０００））／２＋（第２の同時実行機能（ＦｕｎｃＹ）のメモリ消費量平均値（６０００））／２＋．．．．）＝「１０２２９」という計算を行う。第１及び第２の同時実行機能のメモリ消費量平均値を「２」で割っているのは、これらの機能を実行しているスレッドが、５０％程度実行が進んでいることを前提としているものである。このように仮想的に按分するのは、純メモリ消費量における同時実行機能のメモリ消費の寄与がどの程度かについては完全に分別することができないためである。従って、目安メモリ消費量は正確な値ではないが、ある程度の精度でも計算できれば、機能開始処理でもスレッド実行の制御をある程度の精度で実行することができる。また、別途機能別メモリ消費量テーブル１４１を解析して、例えば特定の機能の目安メモリ消費量が特別に大きいなどの問題を抽出することができ、さらにプログラムの改善などを判断することができるようになる。
【００５４】
図１７の処理に戻って、メモリ管理モジュール１４は、機能別メモリ消費量テーブル１４１にレコードを追加する（ステップＳ４９）。例えば図１９の最終行（通番１００）に示すようなレコードを追加する。さらに、メモリ管理モジュール１４は、実行中スレッドテーブル１４２から本スレッドに対応するレコードを削除する（ステップＳ５１）。例えば図２０に示すように、最終行のレコードが削除される。
【００５５】
最後に、メモリ管理モジュール１４は、他スレッド再起動命令を仮想マシン１０に出力する（ステップＳ５３）。これによって、例えばステップＳ９で停止していたスレッドが再起動される。さらに、メモリ管理モジュール１４は、仮想スレッド排他解除命令を仮想マシン１０に出力する（ステップＳ５５）。
【００５６】
以上のように機能終了処理を実施することによって、機能別メモリ消費量テーブル１４１が更新され、後の機能開始処理でより適切なスレッド実行制御を行うことができるようになる。また、別途解析することによって、問題のある機能を特定して改修するなどの処置を行うことができるようになる。
【００５７】
また、図３の例を、本実施の形態で処理した場合（第１のスレッドで実行された機能のメモリ消費量平均値が「５５０」で第２のスレッドで実行された機能のメモリ消費量平均値が「５００」。）には、第１のスレッドで実行された機能については、（１００００−８９５０）×５５０／（５５０＋５００／２）＝７２２となり、第２のスレッドで実行された機能については、（１００００−８９５０）×５００／（５００＋５５０／２）＝６７７となる。このように、図３の例で示した想定のメモリ消費量とは差はあるが、開始時点のメモリ残量と終了時点のメモリ残量との差（＝１０５０）を用いるよりは、より適切な目安メモリ消費量を得ることができている。なお、実際の運用中に、上記のような想定のメモリ消費量を把握することは困難である。
【００５８】
なお、測定対象プログラム１２に、上で述べたようなメモリ管理モジュール１４に対する呼び出し関係を設定するには、既存のアスペクト指向に基づくコンパイラを用いればよい。例えば図２１に示すように、測定対象プログラム１２のソースコードと、メモリ管理モジュール１４の取り付け箇所情報とを、アスペクト指向に基づくコンパイラに入力すると、メモリ管理モジュール１４の呼び出しコードが挿入された測定対象プログラム１２（実行モジュール）が生成される。なお、取り付け箇所情報は、例えば「ソースコードファイル名＋関数名」の一覧表であってもよい。但し、取り付け箇所は、本実施の形態の目的からして、機能の開始地点及び終了地点となる関数である。このような関数があるソースコードファイル名や関数名は、プログラム開発をする上で保守を考慮して、所定のルールに則って付される場合が多い。従って、現実的には、「ソースコードファイル名「〜Ｆｕｎｃｔｉｏｎ」の「ｅｘｅｃｕｔｅ」関数の全て」といった形で、取り付け箇所を指定することが可能である。
【００５９】
以上本発明の一実施の形態を説明したが、本発明はこれに限定されるものではない。例えば、図４において、メモリ管理モジュール１４内に、機能別メモリ消費量テーブル１４１、実行中スレッドテーブル１４２、機能別平均メモリ消費量テーブル１４３を設ける例を示したが、図２２に示すように、例えば上記テーブルを管理するようなデータベースサーバ３０を、別のスレッドとして仮想マシン１０上に設けたり、さらに他のコンピュータ上に設けるような構成であっても良い。
【００６０】
その他、処理結果が変わらなければ、処理ステップの順番を入れ替えても良い場合もある。
【００６１】
また、サーバ・プログラム１１を用いる例を示したが、必ずサーバ・プログラム１１を用いなければならないわけではない。
【００６２】
なお、上で述べたＯＳ等のプログラムを実行するコンピュータにおいては、図２３に示すように、メモリ２５０１（記憶部）とＣＰＵ２５０３（処理部）とハードディスク・ドライブ（ＨＤＤ）２５０５と表示装置２５０９に接続される表示制御部２５０７とリムーバブル・ディスク２５１１用のドライブ装置２５１３と入力装置２５１５とネットワークに接続するための通信制御部２５１７とがバス２５１９で接続されている。ＯＳ及びＷｅｂブラウザを含むアプリケーション・プログラムは、ＨＤＤ２５０５に格納されており、ＣＰＵ２５０３により実行される際にはＨＤＤ２５０５からメモリ２５０１に読み出される。必要に応じてＣＰＵ２５０３は、表示制御部２５０７、通信制御部２５１７、ドライブ装置２５１３を制御して、必要な動作を行わせる。また、処理途中のデータについては、メモリ２５０１に格納され、必要があればＨＤＤ２５０５に格納される。このようなコンピュータは、上で述べたＣＰＵ２５０３、メモリ２５０１などのハードウエアとＯＳ及び必要なアプリケーション・プログラムとが有機的に協働することにより、上で述べたような各種機能を実現する。
【００６３】
（付記１）
仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される複数の機能の実行を制御する制御プログラムであって、
コンピュータのプロセッサに、
前記仮想マシンから、特定の機能の実行開始時における、当該仮想マシンに割り当てられたメモリの残量を取得するステップと、
過去に実行された各前記機能の目安メモリ消費量を実行毎に格納する機能別メモリ消費量テーブルから、前記特定の機能についての前記目安メモリ消費量を抽出し、抽出された前記目安メモリ消費量から前記特定の機能のメモリ消費予測値を算出するメモリ消費予測値算出ステップと、
前記メモリの残量と前記メモリ消費予測値との差が予め定められた閾値未満である場合に、前記特定の機能のスレッドを前記仮想マシンに停止させるステップと、
を実行させるための制御プログラム。
【００６４】
（付記２）
前記メモリの残量と前記メモリ消費予測値との差が前記予め定められた閾値以上である場合には、前記メモリの残量を含む、前記特定の機能のスレッドに関するデータを、実行中の機能のスレッドに関するデータを格納する実行中スレッドテーブルに登録するステップと、
前記仮想マシンから、前記特定の機能の実行終了時における、前記仮想マシンに割り当てられたメモリの残量である当該メモリの第２の残量を取得するステップと、
前記実行中スレッドテーブルから前記特定の機能の前記メモリの残量を取得するステップと、
前記メモリの第２の残量と前記メモリの残量との差である純メモリ消費量を、前記特定の機能と、前記実行中スレッドテーブルから特定される、前記特定の機能と同時実行されている他の機能とで按分して、前記特定の機能についての前記目安メモリ消費量を算出する目安メモリ消費量算出ステップと、
前記特定の機能についての前記目安メモリ消費量を前記機能別メモリ消費量テーブルに登録するステップと、
をさらに前記プロセッサに実行させるための付記１記載の制御プログラム。
【００６５】
（付記３）
前記メモリ消費予測値算出ステップが、
抽出された前記目安メモリ消費量の平均値を算出するステップと、
抽出された前記目安メモリ消費量と前記目安メモリ消費量の平均値との差の絶対値の平均値の所定割合を分散リスク値として算出するステップと、
前記目安メモリ消費量の平均値と前記分散リスク値との和を前記メモリ消費予測値として算出するステップと、
を含む付記１記載の制御プログラム。
【００６６】
（付記４）
前記目安メモリ消費量算出ステップが、
前記特定の機能の前記目安メモリ消費量の平均値を取得するステップと、
前記実行中スレッドテーブルから特定される、前記特定の機能と同時実行されている他の機能の各々について、前記目安メモリ消費量の平均値を取得するステップと、
前記特定の機能の前記目安メモリ消費量の平均値と、前記他の機能の各々の前記目安メモリ消費量の平均値の所定割合とで、前記純メモリ消費量を按分して、前記特定の機能の前記目安メモリ消費量を算出するステップと、
を含む付記２記載の制御プログラム。
【００６７】
（付記５）
前記メモリ消費予測値算出ステップが、
過去に実行された各前記機能の目安メモリ消費量を実行毎に格納する機能別メモリ消費量テーブルから、前記特定の機能についての前記目安メモリ消費量を所定実行数分抽出できたか判断するステップ
を含み、
前記目安メモリ消費量を所定実行数分抽出できない場合には、前記メモリの残量を含む、前記特定の機能のスレッドに関するデータを、実行中の機能のスレッドに関するデータを格納する実行中スレッドテーブルに登録するステップ
をさらに実行させるための付記１記載の制御プログラム。
【００６８】
（付記６）
仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される複数の機能の実行を制御する制御部を有するコンピュータにより実行させる制御方法であって、
前記制御部が、前記仮想マシンから、特定の機能の実行開始時における、当該仮想マシンに割り当てられたメモリの残量を取得するステップと、
前記制御部が、過去に実行された各前記機能の目安メモリ消費量を実行毎に格納する機能別メモリ消費量テーブルから、前記特定の機能についての前記目安メモリ消費量を抽出し、抽出された前記目安メモリ消費量から前記特定の機能のメモリ消費予測値を算出するメモリ消費予測値算出ステップと、
前記メモリの残量と前記メモリ消費予測値との差が予め定められた閾値未満である場合に、前記制御部が、前記特定の機能のスレッドを前記仮想マシンに停止させるステップと、
を含む制御方法。
【００６９】
（付記７）
仮想マシン上で実行されるプログラムに含まれ、スレッドとして実行される複数の機能の実行を制御する制御部を有し、
前記制御部が、
前記仮想マシンから、特定の機能の実行開始時における、当該仮想マシンに割り当てられたメモリの残量を取得する手段と、
過去に実行された各前記機能の目安メモリ消費量を実行毎に格納する機能別メモリ消費量テーブルから、前記特定の機能についての前記目安メモリ消費量を抽出し、抽出された前記目安メモリ消費量から前記特定の機能のメモリ消費予測値を算出するメモリ消費予測値算出手段と、
前記メモリの残量と前記メモリ消費予測値との差が予め定められた閾値未満である場合に、前記特定の機能のスレッドを前記仮想マシンに停止させる手段と、
を有するコンピュータ。
【図面の簡単な説明】
【００７０】
【図１】ＯＳとプロセスの関係を表す模式図である。
【図２】仮想マシンとスレッドの関係を表す模式図である。
【図３】スレッドで実行される機能のメモリ消費量を説明するための模式図である。
【図４】本発明の実施の形態におけるプログラム構成図である。
【図５】機能別メモリ消費量テーブルの一例を示す図である。
【図６】実行中スレッドテーブルの一例を示す図である。
【図７】機能別平均メモリ消費量テーブルの一例を示す図である。
【図８】本発明の実施の形態におけるプログラム構成の詳細図である。
【図９】本発明の実施の形態における処理の概要を示す図である。
【図１０】メモリ管理モジュールの機能開始処理の処理フローを示す図である。
【図１１】機能別メモリ消費予測値算出処理の処理フローを示す図である。
【図１２】設定パラメータの一例を示す図である。
【図１３】機能別メモリ消費量テーブルから抽出されるデータの一例を示す図である。
【図１４】実行中スレッドテーブルに対する処理の第１段階の例を示す図である。
【図１５】実行中スレッドテーブルに対する処理の第２段階の例を示す図である。
【図１６】実行中スレッドテーブルに対する処理の第３段階の例を示す図である。
【図１７】メモリ管理モジュールの機能終了処理の処理フローを示す図である。
【図１８】目安メモリ消費量計算処理の処理フローを示す図である。
【図１９】機能別メモリ消費量テーブルへの登録を説明するための図である。
【図２０】実行中スレッドテーブルに対する処理の第４段階の例を示す図である。
【図２１】メモリ管理モジュールへの呼び出しコードを含む測定対象プログラムを生成する方法を説明するための模式図である。
【図２２】本発明の実施の形態における他のプログラム構成図である。
【図２３】コンピュータの機能ブロック図である。
【符号の説明】
【００７１】
１  ＯＳ    １０  仮想マシン
１１  サーバ・プログラム    １２  測定対象プログラム
１３  各種ライブラリ    １４  メモリ管理モジュール
１４１  機能別メモリ消費量テーブル
１４２  実行中スレッドテーブル
１４３  機能別平均メモリ消費量テーブル
【図１】
0004935626.tif 000002
【図２】
0004935626.tif 000003
【図３】
0004935626.tif 000004
【図４】
0004935626.tif 000005
【図５】
0004935626.tif 000006
【図６】
0004935626.tif 000007
【図７】
0004935626.tif 000008
【図８】
0004935626.tif 000009
【図９】
0004935626.tif 000010
【図１０】
0004935626.tif 000011
【図１１】
0004935626.tif 000012
【図１２】
0004935626.tif 000013
【図１３】
0004935626.tif 000014
【図１４】
0004935626.tif 000015
【図１５】
0004935626.tif 000016
【図１６】
0004935626.tif 000017
【図１７】
0004935626.tif 000018
【図１８】
0004935626.tif 000019
【図１９】
0004935626.tif 000020
【図２０】
0004935626.tif 000021
【図２１】
0004935626.tif 000022
【図２２】
0004935626.tif 000023
【図２３】
0004935626.tif 000024