図1は、本発明の実施の形態のJavaVMが動作する計算機システム101の構成及び入出力データを示す図である。
本発明の実施の形態の計算機システム101では、Java言語によって記述されたプログラムがコンパイルされることによって、Javaクラスファイルが作成される。さらに、Javaクラスファイルが実行されることによって所定の業務処理が実行される。
計算機システム101は、プロセッサ131、主記憶107、補助記憶102、出力装置130、及び入力装置132を含む。プロセッサ131、主記憶107、補助記憶102、出力装置130、及び入力装置132は、バス129を介して互いに接続される。
プロセッサ131は、主記憶107に記憶された各種プログラムを実行することによって、各種処理を実行する。主記憶107は、プログラム、プログラムの実行に必要な情報及びプログラムの処理結果を記憶する。主記憶107は、揮発性メモリであってもよいし、不揮発性メモリであってもよい。主記憶107は、Javaコンパイラ108、JavaVM109、及びオペレーティングシステム128を記憶する。
補助記憶102は、業務処理の実行に使用されるJavaクラスファイル103、Javaクラスファイルを生成するためのJavaソースファイル104、処理に使用されるファイル105、及びJavaVM109の設定ファイル106を含む。
入力装置132は、計算機システム101に必要な情報を入力するためのインタフェースである。入力装置132は、例えば、キーボード又はマウスなどである。出力装置130は、処理結果などの情報を外部に出力する装置である。出力装置130は、例えば、ディスプレイなどである。
ここで、主記憶107に記憶されるJavaVM109について説明する。JavaVM109は、不要になったメモリ領域を自動的に回収するメモリ管理機構を備える言語処理システムである。
JavaVM109は、メソッド読み取り部113、動的コンパイラ部116、メモリ管理部124、及びメソッド実行部123を含む。メソッド読み取り部113、動的コンパイラ部116、メモリ管理部124、及びメソッド実行部123は、プロセッサ131によって実行されるプログラムである。また、JavaVM109は、コンパイルコード格納領域117、Javaヒープ領域122、及び外部ヒープ領域110を含む。
メソッド読み取り部113は、プロセッサ131によって実行されることによって、Javaクラスファイル103からメソッドを読み込み、メソッド情報118を作成する。動的コンパイラ部116は、プロセッサ131によって実行されることによって、メソッド情報118に基づいて、メソッドを動的にコンパイルする。
メモリ管理部124は、プロセッサ131によって実行されることによって、JavaVM109で使用するメモリ領域を管理する。メモリ管理部124は、ページトラップ検出部111、インポート実行部114、GC実行部115、リークオブジェクト検出部120、及びメモリ確保部121を含む。各部の詳細については、図2にて後述する。
メソッド実行部123は、プロセッサ131によって実行されることによって、メソッドを実行する。メソッド実行部123は、コンパイルコード実行部126及びインタプリタ実行部127を含む。
コンパイルコード格納領域117は、動的コンパイラ部116による動的コンパイルの結果であるコンパイルコード125を格納する。Javaヒープ領域122は、メソッド情報118及びオブジェクト119を格納する。外部ヒープ領域110は、リークオブジェクト112を格納する。Javaヒープ領域122及び外部ヒープ領域110には、オブジェクトがポインタによって接続された木構造を構成されて格納されている。
Javaソースファイル104は、Javaコンパイラ108によって、インタプリタ実行部127が解釈及び実行可能な形式であるバイトコードにコンパイルされると、Javaクラスファイル103が生成される。Javaクラスファイル103は、JavaVM109に入力されると、メソッド読み取り部113によって解析され、Javaヒープ領域122にメソッド情報118が作成される。
プロセッサ131は、プログラムを実行する場合には、まず、インタプリタ実行部127がメソッド情報118を読み込み、メソッドをインタプリタ実行する。一方、インタプリタ実行において実行頻度が高いメソッドについては、動的コンパイラ部116がメソッド情報118を読み込み、動的にコンパイルし、コンパイルコード125をコンパイルコード格納領域117に作成する。そして、コンパイルコード実行部126がコンパイルコード125を読み込み、メソッドをコンパイルコード実行する。なお、JavaVM109は、最初から最後までメソッドをインタプリタ実行してもよいし、最初からコンパイルコード実行してもよい。
図2は、本発明の実施の形態であるJavaVM109におけるメモリ管理部124の構成と入出力データを示す図である。
まず、メソッド実行部123によるメソッド実行処理の概要を簡単に説明すると、プロセッサ131は、実行する命令がメモリ確保命令の場合に、メモリ確保部121にJavaヒープ領域122へのメモリ確保処理を要求する。
メモリ確保部121は、メソッド実行部123からメモリ確保処理要求を受け付けると、Javaヒープ領域122へのメモリ確保を試みる。ここで、メモリ確保に成功した場合には、確保されたメモリ領域を呼び元に返却する。メモリ確保に失敗した場合には、GC実行部115を呼び出してGC処理を実行し、Javaヒープ領域122で不要になったメモリ領域を開放する。そして、再びメモリ確保を試み、さらに失敗した場合にはメモリ不足エラーを発生させる。
ここで、メモリ管理部124の各構成について概要を以下に説明する。
メモリ管理部124は、前述のように、ページトラップ検出部111、インポート実行部114、GC実行部115、リークオブジェクト検出部120、及びメモリ確保部121を含む。メモリ管理部124は、さらに、リークオブジェクト検出管理情報208、Javaヒープ領域管理テーブル213、外部ヒープ領域管理テーブル214、ファイル管理テーブル215、外部ヒープ領域管理情報216、ファイルオフセットマップ217、及びインポート実行管理情報218を含む。
リークオブジェクト検出管理情報208は、リークオブジェクトを検出するための処理に必要な情報を格納する。リークオブジェクト検出管理情報208の詳細は、図3に後述する。
Javaヒープ領域管理テーブル213は、Javaヒープ領域122を特定する情報が格納される。Javaヒープ領域管理テーブル213の詳細は、図4Aにて後述する。外部ヒープ領域管理テーブル214は、外部ヒープ領域を特定する情報が格納される。外部ヒープ領域管理テーブル214の詳細は、図4Bにて後述する。
ファイル管理テーブル215は、外部ヒープ領域として使用されるファイル105を特定するファイルポインタを格納する。ファイル管理テーブル215の詳細は、図4Cにて後述する。
外部ヒープ領域管理情報216は、外部ヒープ領域110として使用する媒体に関する情報を格納する。外部ヒープ領域管理情報216の詳細は、図3にて後述する。
ファイルオフセットマップ217は、外部ヒープ領域として使用されるファイル105と論理記憶領域とを関連付けるために使用される。ファイルオフセットマップ217の詳細は、図9にて後述する。
インポート実行管理情報218は、Javaヒープ領域122に格納されたオブジェクトを外部ヒープ領域110に移行する際に必要な情報を格納する。インポート実行管理情報218の詳細は、図3にて後述する。
また、本発明の実施の形態では、リークオブジェクト112の再配置先となる外部ヒープ領域110として、主記憶107以外のメモリ及びファイル105などを使用できる。ファイル105は、メモリマップを用いることによってメモリと同様に使用してもよいし、論理アドレス空間とファイルオフセットを対応付けるためのファイルオフセットマップ217を使用してメモリとは別に管理してもよい。
なお、本発明の実施の形態では、外部ヒープ領域110としてファイル105を使用し、ファイルオフセットマップ217を使用してメモリとは別に管理する。また、外部ヒープ領域110として使用される媒体に関する情報は、外部ヒープ領域管理情報216含まれる。
続いて、リークオブジェクト検出部120の構成について説明する。
リークオブジェクト検出部120は、リークオブジェクト検査部206及びリークオブジェクト判定部207を含む。リークオブジェクト検査部206は、Javaヒープ領域122に記憶されているオブジェクトのアクセス状況を検査する。リークオブジェクト判定部207は、アクセスされていないオブジェクト(非アクセスオブジェクト)がリークオブジェクトであるか否かを判定する。
リークオブジェクト検査部206は、アクセス領域検査部201、アクセスアドレステーブル202、非アクセスオブジェクトアドレス収集部203、及び非アクセスオブジェクトアドレステーブル205を含む。
アクセス領域検査部201は、プロセッサ131によって実行されることによって、Javaヒープ領域122に記憶された情報がアクセスされたか否かを領域ごとに検査する。アクセス領域検査部201の処理の詳細は、図11にて後述する。
アクセスアドレステーブル202は、メソッドの実行などによってアクセスされた領域のアドレスが格納される。アクセスアドレステーブル202の詳細は、図5にて後述する。
非アクセスオブジェクトアドレス収集部203は、プロセッサ131によって実行されることによって、アクセスされていないオブジェクトのアドレスを収集する。非アクセスオブジェクトアドレス収集部203の処理の詳細は、図12にて後述する。
非アクセスオブジェクトアドレステーブル205は、アクセスされていないオブジェクトのアドレスを格納する。非アクセスオブジェクトアドレステーブル205の詳細は、図6にて後述する。
ここで、リークオブジェクト検出部120の処理の概要について説明する。
オペレーティングシステム128は、ページトラップが発生したことを検知すると、その旨をページトラップ検出部111に通知する。
ページトラップ検出部111は、オペレーティングシステム128からページトラップが発生した旨を通知されると、通知内容に基づいて、アクセス領域検査部201又はインポート実行部114に処理要求を送信する。
アクセス領域検査部201は、ページトラップ検出部111から処理要求を受け付けると、アクセス領域検査処理を実行し、アクセスアドレステーブル202を更新する。
非アクセスオブジェクトアドレス収集部203は、非アクセスオブジェクトアドレス収集処理要求204を受け付けると、リークオブジェクト検出管理情報208に基づいて、非アクセスオブジェクトアドレス収集処理を実行し、非アクセスオブジェクトアドレステーブル205を更新する。
リークオブジェクト判定部207は、リークオブジェクト検出管理情報208に基づいて、非アクセスオブジェクトアドレステーブル205に登録されたオブジェクトがリークオブジェクトであるか否かを判定する。
インポート実行部114は、ページトラップ検出部111から処理要求を受け付けると、インポート実行管理情報218に基づいて、インポート処理を実行する。インポート処理では、アクセスされた外部ヒープ領域110に配置されたリークオブジェクト112をJavaヒープ領域122に再配置する。外部ヒープ領域110としてファイル105が使用され、ファイルオフセットマップ217に基づいて主記憶と別に管理されている場合には、ファイルオフセットマップ217に基づいて、論理アドレス空間とファイルオフセットのマッピングを解決する。
GC実行部115は、不要になったオブジェクトを特定し、メモリ領域から解放する。GC実行部115は、オブジェクト種別判定部209、再配置アドレス計算部210、オブジェクト参照更新部211、及び再配置実行部212を含む。
オブジェクト種別判定部209は、Javaヒープ領域122に記憶されたオブジェクトにオブジェクト種別を付与し、リークオブジェクト判定部207を実行することによって、当該オブジェクトがリークオブジェクトであるか否かを判定する。オブジェクト種別判定部209の処理の詳細は、図21にて後述する。また、オブジェクト種別については、図8に示す。
再配置アドレス計算部210は、再配置対象のオブジェクトをオブジェクト種別に基づいて、再配置先のアドレスを計算する。再配置アドレス計算部210の処理の詳細は、図30にて後述する。
オブジェクト参照更新部211は、再配置アドレス計算部210によって算出された再配置先アドレスで再配置対象のオブジェクトの参照情報を更新する。オブジェクト参照更新部211は、GC処理において実行される。
再配置実行部212は、再配置アドレス計算部210によって算出されたオブジェクトの再配置先アドレスに基づいて、対象のオブジェクトを再配置する。再配置実行部212の処理の詳細は、図31にて後述する。
図3は、本発明の実施の形態のリークオブジェクト検出管理情報208、外部ヒープ領域管理情報216、及びインポート実行管理情報218の一例を示す図である。
リークオブジェクト検出管理情報208は、リークオブジェクトを検出するための処理に必要な項目を格納する。リークオブジェクト検出管理情報208は、リークオブジェクト検出実行フラグ3001、リークオブジェクト検出実行条件3002、リークオブジェクト検出領域ページ数3003、アクセスアドレス収集回数3004、リークオブジェクト条件3005、及びオブジェクト整列実行フラグ3006を含む。
リークオブジェクト検出実行フラグ3001は、リークオブジェクト検出が実行中か否かを示す。リークオブジェクト検出実行フラグ3001の値が“1”であればリークオブジェクト検出実行中であることを示し、“0”であればリークオブジェクト検出実行中でないことを示す。なお、JavaVM起動時のリークオブジェクト検出実行フラグ3001の初期値は、リークオブジェクト検出実行条件3002の値によって決定される。
リークオブジェクト検出実行条件3002は、リークオブジェクトの検出処理を実行する条件であるJavaヒープ領域122のメモリ使用量を格納する。例えば、リークオブジェクト検出実行条件3002の値が“256M”であれば、Javaヒープ領域122のメモリ使用量が256MB以上の場合にリークオブジェクトの検出処理を実行し、メモリ使用量が256MBを下回っている場合にはリークオブジェクトの検出処理を実行しない。また、リークオブジェクト検出実行条件3002の値が“0以下”の場合には、リークオブジェクトの検出処理を常に実行するように設定することができる。リークオブジェクト検出実行条件3002の値がJavaヒープ領域122のサイズより大きい値の場合には、リークオブジェクトの検出処理を常に実行しないように設定することができる。
リークオブジェクト検出領域ページ数3003は、リークオブジェクト検出領域3201の範囲をページ単位で格納する。リークオブジェクト検出領域3201は、リークオブジェクトの検出処理を実行する対象の領域である。リークオブジェクト検出領域3201の詳細は、図5にて後述する。例えば、リークオブジェクト検出領域ページ数3003の値が“16K”であれば、Javaヒープ領域122の先頭から16KBのサイズのページがリークオブジェクト検出領域3201となる。ただし、リークオブジェクト検出領域ページ数3003にJavaヒープ領域122のメモリ使用量を超えるページ数が指定された場合には、Javaヒープ領域122のメモリ使用量に基づいたページ数をリークオブジェクト検出領域ページ数3003に格納する。
アクセスアドレス収集回数3004は、アクセス領域検査部201によるアクセスアドレス収集処理において、リークオブジェクト検出領域3201の各ページに対するアクセスアドレス収集処理の実行回数の上限を保持する。例えば、アクセスアドレス収集回数3004の値が“3”である場合、アクセスアドレス収集処理を3回実行したページのページトラップが解除される。
リークオブジェクト条件3005は、リークオブジェクトの判定基準である非アクセスオブジェクトアドレステーブル205の非アクセス回数3302の閾値を示す。例えば、リークオブジェクト条件3005の値が“5”である場合には、リークオブジェクト判定部207によって、非アクセスオブジェクトアドレステーブル205の非アクセス回数3302の値が5以上のオブジェクトがリークオブジェクトと判定される。
オブジェクト整列実行フラグ3006は、再配置実行処理の場合に、オブジェクトのアクセス傾向に基づいてオブジェクトを整列するか否かを示す。オブジェクト整列実行フラグ3006の値が“1”であればオブジェクトを整列し、“0”であればオブジェクトを整列しない。
外部ヒープ領域管理情報216は、外部ヒープ領域種別3007を含む。外部ヒープ領域種別3007は、外部ヒープ領域110の種別を示す。例えば、外部ヒープ領域種別3007の値が“0”であれば、外部ヒープ領域110はメモリに確保される領域であることを表す。また、“1”であればファイル105に確保される領域であることを表し、ファイルオフセットマップ217によりメモリとは別に管理される。なお、本発明の実施の形態では、外部ヒープ領域110は、ファイル105に確保される領域であり、ファイルオフセットマップ217によってメモリとは別に管理される。
インポート実行管理情報218は、インポート範囲3008及び参照解決フラグ3009を含む。インポート処理は、インポート実行部114がプロセッサ131に処理されることによって実行される。インポート処理は、外部ヒープ領域110に格納されたオブジェクトをJavaヒープ領域122に移動させる処理である。インポート処理の詳細は、図33にて後述する。
インポート範囲3008は、アクセスされたオブジェクトのオブジェクト参照を辿ることによって到達可能な他のリークオブジェクトを、外部ヒープ領域110からJavaヒープ領域122に再配置する範囲を格納する。例えば、インポート範囲3008の値が“2”である場合には、アクセスされたオブジェクトのオブジェクト参照を2段階辿ることによって到達可能なリークオブジェクトを外部ヒープ領域110からJavaヒープ領域122に再配置する。また、インポート範囲3008の値が“0”である場合には、直接アクセスされたオブジェクトだけをインポート処理の対象とすることができる。
さらに、インポート範囲3008の値が負の数である場合には、直接アクセスされたオブジェクトであってもインポート処理の対象としないとすることができる。例えば、対象のオブジェクトのアクセス頻度が非常に少ない場合などには、Javaヒープ領域122にオブジェクトを再配置しても、GC処理によって外部ヒープ領域110に当該オブジェクトが再配置される可能性が高い。このように、直接アクセスされたオブジェクトをインポート処理の対象としないことによって、インポート処理及びGC処理によって生じるオーバーヘッドを削減することができる。
参照解決フラグ3009は、外部ヒープ領域110に配置されたリークオブジェクト112のオブジェクト参照をGC処理時に解決するか否かを示す。参照解決フラグ3009の値が“1”であれば前述のオブジェクト参照をGC処理において解決することを示し、“0”であればインポート処理において解決することを示している。
なお、オブジェクト参照をGC処理において解決するのであれば、外部ヒープ領域110に再配置されたリークオブジェクト112は、GC処理におけるオブジェクト参照更新処理及びオブジェクト参照更新処理の対象となる。一方、オブジェクト参照をインポート処理において解決するのであれば、外部ヒープ領域110に再配置されたリークオブジェクトはGC処理の対象外となる。なお、本発明の実施の形態では、リークオブジェクト112のオブジェクト参照をインポート処理において解決し、外部ヒープ領域110に配置されたオブジェクトはGC処理の対象外とする。
リークオブジェクト検出管理情報208のリークオブジェクト検出実行フラグ3001以外の各フィールドは、設定ファイル106又はJavaVM起動時の入力装置132からの入力によって利用者が指定することができる。
図4Aは、本発明の実施の形態のJavaヒープ領域122を管理するためのJavaヒープ領域管理テーブル213の一例を示す図である。
Javaヒープ領域管理テーブル213は、領域先頭3101、生存領域終端3102、検出領域終端3103、未使用領域先頭3104、及び領域終端3105を含む。
領域先頭3101は、Javaヒープ領域122の先頭アドレスを格納する。領域終端3105は、Javaヒープ領域122の終端アドレスを格納する。
生存領域終端3102は、生存オブジェクト配置領域1201の終端アドレスを格納する。なお、生存領域終端3102に格納されるアドレスは、アクセスオブジェクト配置領域1202の先頭アドレスと同じである。
検出領域終端3103は、リークオブジェクト検出管理情報208のリークオブジェクト検出領域ページ数3003に基づいて設定されるリークオブジェクト検出領域の終端アドレスを格納する。
未使用領域先頭3104は、Javaヒープ領域122の未使用領域の先頭アドレスを格納する。なお、未使用領域先頭3104が保持するアドレスは、アクセスオブジェクト配置領域1202の終端アドレスと同じである。
図4Bは、本発明の実施の形態の外部ヒープ領域110を管理するための外部ヒープ領域管理テーブル214の一例を示す図である。外部ヒープ領域管理テーブル214は、外部ヒープ領域110が主記憶107に確保された場合に使用される。
領域先頭3106は、外部ヒープ領域110の先頭アドレスを格納する。領域終端3108は、外部ヒープ領域110の終端アドレスを格納する。未使用領域先頭3107は、外部ヒープ領域110の未使用領域の先頭アドレスを格納する。
図4Cは、本発明の実施の形態の外部ヒープ領域110が補助記憶102に格納されたファイル105に確保される場合に使用されるファイル管理テーブル215の一例を示す図である。
ファイルポインタ3109は、ファイル105のファイルポインタを格納する。ファイルオフセット3110は、ファイル105のファイルオフセットを格納する。
JavaVM109の実行性能を考慮すると、オブジェクトを物理アドレス空間に配置したほうが性能がよい。しかし、アクセス頻度が少ないためにメモリリークが発生した可能性が高いと判定されたオブジェクトを格納する外部ヒープ領域110では、論理アドレス空間を適用としても実行性能を著しく低下させることはない。本発明の実施の形態では、外部ヒープ領域110を物理アドレス空間及び論理アドレス空間のいずれにも確保することを可能とし、物理アドレス空間及び論理アドレス空間の両方を確保して運用することも可能である。
なお、本発明の実施の形態では、Javaヒープ領域122を物理アドレス空間、外部ヒープ領域110を論理アドレス空間に確保し、外部ヒープ領域110に配置されるリークオブジェクト112の実体は、リークオブジェクト112の論理アドレスに対応するファイル105のオフセットの位置に記録する。論理アドレスとファイルオフセットのマッピングを保持するファイルオフセットマップ217については、図9にて後述する。
図5は、本発明の実施の形態のリークオブジェクト検出領域3201及びアクセスアドレステーブル202を示す図である。
リークオブジェクト検出領域3201は、前述のように、リークオブジェクトの検出処理を実行する対象の領域である。リークオブジェクト検出管理情報208のリークオブジェクト検出領域ページ数3003に基づいて、Javaヒープ領域122にページが設定される。
アクセスアドレステーブル202は、リークオブジェクト検出領域3201の各ページに対応するブロックを含む。各ブロックは、リークオブジェクト検出管理情報208のアクセスアドレス収集回数3004に基づいた数のフィールドを有する。当該フィールドは、アクセスアドレス402を格納し、初期状態では未登録状態を表すNULL値が格納される。
図6は、本発明の実施の形態の非アクセスオブジェクトアドレステーブル205の一例を示す図である。
非アクセスオブジェクトアドレステーブル205は、非アクセスオブジェクトアドレス3301及び非アクセス回数3302を含む。
非アクセスオブジェクトアドレス3301は、非アクセスオブジェクト502のアドレスを格納する。非アクセス回数3302は、非アクセスオブジェクトアドレス3301によって特定される非アクセスオブジェクト502が非アクセスオブジェクトアドレス収集部203によって実行された非アクセスオブジェクトアドレス収集処理によって連続して収集された回数を格納する。非アクセス回数3302の値は大きいほど現在アクセスされない傾向にあることを示す。
なお、非アクセスオブジェクトアドレス3301の各フィールドは、オブジェクト参照更新部211によるオブジェクト参照更新処理の対象である。そのため、非アクセスオブジェクトアドレス3301によって特定されるオブジェクトがGC処理によって再配置されると、非アクセスオブジェクトアドレス3301に格納されるアドレスも更新される。
図7は、本発明の実施の形態のオブジェクト構造を示す図である。オブジェクトは、オブジェクトヘッダ3401とオブジェクトデータ3402から構成される。
オブジェクトヘッダ3401は、オブジェクトの管理情報である。オブジェクトデータ3402は、オブジェクトのデータ本体である。
なお、オブジェクトへのポインタの下位数ビットは、オブジェクトヘッダ3401のサイズに応じて0とすることができるため、ビットフラグとして使用可能である。例えば、オブジェクトヘッダ3401のサイズが8バイトである場合、オブジェクトへのポインタの下位3ビットは0になる。本発明の実施の形態では、オブジェクトへのポインタの下位数ビットをビットフラグとして使用する場合がある。
図8は、本発明の実施の形態のオブジェクト種別ビットの一例を示す図である。オブジェクト種別ビットの値は、オブジェクトの種別に対応する。本発明の実施の形態では、オブジェクトヘッダ3401に含まれる2ビットをオブジェクト種別ビットとして使用する。
具体的には、オブジェクト種別ビット3501が“00”の場合には、不要なオブジェクトである“デッド”オブジェクトであることを示す。また、オブジェクト種別ビット3501が“11”の場合には、メモリリークが発生している可能性が高いオブジェクトである”リーク”オブジェクトであることを示す。
さらに、オブジェクト種別ビット3501が“10”の場合には、直近のメソッド実行中にアクセスされたことがアクセスアドレステーブル202に記録されたオブジェクトである“アクセス”オブジェクトであることを示す。オブジェクト種別ビット3501が“01”の場合には、直近のメソッド実行ではアクセスされていないが、比較的最近にアクセスされた“生存”オブジェクトであることを示す。
図9は、本発明の実施の形態のファイルオフセットマップ217の一例を示す図である。ファイルオフセットマップ217は、オブジェクトアドレス3701及びファイルオフセット3702を含む。
オブジェクトアドレス3701は、外部ヒープ領域110に仮想的に配置されたオブジェクトの論理アドレスを格納する。ファイルオフセット3702は、オブジェクトアドレス3701が指し示すオブジェクトの実体が記録されたファイル105のファイルオフセットを保持する。ファイルオフセットとは、ファイル内での相対位置を示す。
GC処理により、Javaヒープ領域122から外部ヒープ領域110にオブジェクトが再配置される場合には、仮想的な論理アドレスを再配置先とし、オブジェクトアドレス3701に記録する。そして、当該オブジェクトの参照元オブジェクトには、再配置先とされた仮想的な論理アドレスをオブジェクト参照として設定する。
インポート処理により、外部ヒープ領域110からJavaヒープ領域122にオブジェクトが再配置される場合には、アクセスされた論理アドレスに基づいてオブジェクトアドレス3701を順に検索する。そして、該当するオブジェクトアドレス3701が検索された場合には、対応するファイルオフセット3702のフィールドから、アクセスされたオブジェクトの実体が記録されたファイル105のファイルオフセットを取得し、ファイル105に記録されたオブジェクトの実データにアクセスする。
例えば、アクセスされた論理アドレスが“0x642a4ab0”であった場合、当該アドレスは、オブジェクトアドレスのフィールド3703が保持する論理アドレスより大きく、オブジェクトアドレスのフィールド3704が保持する論理アドレスより小さいため、オブジェクトの実体は、オブジェクトアドレスのフィールド3703に対応するファイルオフセットのフィールド3705から取得される。なお、外部ヒープ領域110を対象とするGC処理においてオブジェクトの実データにアクセスする場合も、同様の手順によって実データにアクセスすることができる。また、インポート処理の際には、外部ヒープ領域110からJavaヒープ領域122に再配置されたオブジェクトを特定するファイルオフセットマップ217のオブジェクトアドレス3701をNULL値で更新しておく。
ここで、オブジェクトアドレス3701にNULL値が格納されている場合には、オブジェクトアドレス3701によって特定される仮想的なオブジェクトと、それに対応するオブジェクトの実体が不要であることを表す。また、ファイルオフセット3702に負数が保持されている場合には、対応するオブジェクトの実体を再配置している途中であることを示し、インポート処理におけるオブジェクトの実体へのアクセスは、オブジェクトの実体の再配置が完了するまで待機させることができる。
以下、本発明の実施の形態のリークオブジェクトを検出する方法の概要を説明する。
図10は、本発明の実施の形態のページトラップ検出部111、メソッド実行部123、及びリークオブジェクト検査部206による処理の実行遷移を示す図である。
本発明の実施の形態のリークオブジェクト検出方法では、まず、メソッド実行の前にアクセス領域検査前処理を実行する(ステップ301)。メソッド実行中には、アクセス領域検査処理を実行し(ステップ306)、リークオブジェクト検査処理を終了する前に非アクセスオブジェクトアドレス収集処理を実行する(ステップ311)。
アクセス領域検査前処理では、Javaヒープ領域122のリークオブジェクト検出領域3201に対し、メソッド実行中におけるリークオブジェクト検出領域3201に格納されたオブジェクトに対するアクセスを検知するためのページトラップを設定する。状態302は、ページトラップ設定後のリークオブジェクト検出領域3201の状態である。図10では、Javaヒープ領域122を4つのページに分割し、アクセスされていないページに斜線を付している。状態302は、すべてのページがアクセスされていない状態を示している。
アクセス領域検査前処理301が終了すると、プロセッサ131は、メソッドを実行する(ステップ303)。なお、アクセス領域検査前処理の詳細については、図16にて後述する。
プロセッサ131は、メソッド実行中にリークオブジェクト検出領域3201に含まれるオブジェクトにアクセスされると、オペレーティングシステム128を経由して、ページトラップ検出部111に通知する(ステップ304)。
ページトラップ検出部111は、通知された内容に基づいて、アクセス領域検査部201にアクセス領域検査処理を要求する(ステップ305)。さらに、メソッド実行部123による処理からアクセス領域検査部201による処理に遷移する(ステップ306)。
アクセス領域検査処理を実行後は、再びメソッド実行部123による処理に実行が遷移し、メソッド実行が継続される(ステップ307)。この時点で、アクセス領域検査実行後のリークオブジェクト検出領域3201の状態は、状態308のようになる。状態308では、アクセスされたページを空白として示している。なお、アクセス領域検査処理の概要は図11にて後述し、詳細は図17にて後述する。
プロセッサ131は、メソッド実行が継続されると、リークオブジェクト検出領域3201のページトラップをアクセス状況に応じて解除する。例えば、リークオブジェクト検出領域3201の状態は、順次、状態309及び状態310のようになる。
ここで、プロセッサ131は、非アクセスオブジェクトアドレス収集処理要求204を受け付けると、メソッド実行部123の処理から非アクセスオブジェクトアドレス収集部203の処理に遷移し(ステップ311)、リークオブジェクト検査処理を終了する。なお、非アクセスオブジェクト収集処理の概要は図12にて後述し、詳細は図18にて後述する。
なお、本発明の実施の形態では、GC実行部115によって非アクセスオブジェクトアドレス収集処理が要求される。アクセス領域検査処理の実行回数又はアクセス領域検査の実行時間に基づいて、アクセス領域検査部201によって非アクセスオブジェクトアドレス収集処理の実行を要求するようにしてもよい。
また、外部ヒープ領域110には、メソッド実行中に外部ヒープ領域110に格納されたリークオブジェクト112に対するアクセスを検知するためのページトラップが設定されている。メソッド実行中に外部ヒープ領域110に格納されたリークオブジェクト112にアクセスされると、その旨がページトラップ検出部111に通知される。ページトラップ検出部111は、通知の内容に基づいて、インポート実行部114にインポート処理を要求する。
プロセッサ131は、インポート処理が要求されると、メソッド実行部123による処理からインポート実行部114による処理に実行を遷移させ、インポート処理を実行する。インポート処理は、外部ヒープ領域110に再配置することによって、GC処理の対象外とされていたリークオブジェクト112を、Javaヒープ領域122に再配置することによってGC処理の対象に戻す処理である。インポート処理の実行後は、メソッド実行部123の処理に再び実行が遷移し、メソッド実行を継続する。なお、インポート処理の詳細については、図33にて後述する。
図11は、本発明の実施の形態のアクセス領域検査部201によるアクセス領域検査処理の概要を示す図である。
アクセス領域検査処理では、アクセスページ408のページトラップが解除される(ステップ406)。なお、アクセスページ408とは、メソッドの実行によってアクセスされたアクセスオブジェクト404が配置されたリークオブジェクト検出領域3201に含まれるページである。リークオブジェクト検出領域3201の状態は、ページトラップを解除する前後において、状態401から状態407のように変化する。
また、アクセスページ408のページトラップを解除する場合には、必要とするリークオブジェクトの検出精度に応じて、実際にアクセスされたアドレスであるアクセスアドレス402をアクセスアドレステーブル202に登録する(ステップ405)。
なお、アクセスオブジェクト404の先頭アドレスであるアクセスオブジェクトアドレス403であってもよい。この場合には、アクセス領域検査処理307のオーバーヘッドは大きくなるが、アクセスオブジェクトアドレス403を取得する処理を以降省略することができる。本発明の実施の形態では、アクセス領域検査処理307ではアクセスアドレス402をアクセスアドレステーブル202に登録し、GC処理において必要に応じてアクセスアドレス402からアクセスオブジェクトアドレス403を取得する。
図12は、本発明の実施の形態の非アクセスオブジェクトアドレス収集部203による非アクセスオブジェクトアドレス収集処理の概要を示す図である。
非アクセスオブジェクトアドレス収集処理では、非アクセスページ501に配置されたオブジェクトである非アクセスオブジェクト502が取得される。そして、非アクセスオブジェクト502の先頭アドレスである非アクセスオブジェクトアドレス503が非アクセスオブジェクトアドレステーブル205に登録される(ステップ504)。
なお、非アクセスページ501とは、リークオブジェクト検出領域3201に含まれ、アクセス領域検査処理307によってページトラップが解除されなかったページである。また、本発明の実施の形態では、オブジェクト全体が非アクセスページ501に含まれない場合には、アクセスオブジェクト404として扱っている。
以下、本発明の実施の形態によるリークオブジェクト検出方法における各部の処理について説明する。
図13は、本発明の実施の形態のメソッド実行処理の手順を示すフローチャートである。本処理は、プロセッサ131がメソッド実行部123を処理することによって実行される。
プロセッサ131は、メソッド実行部123を実行する前に、まず、JavaVM109が受け付けたJavaクラスファイル103を解析する。次に、メソッド読み取り部113によって、Javaクラスファイル103からメソッドを抽出し、動的コンパイラ部116によって、コンパイルコード125を生成する。プロセッサ131は、生成されたコンパイルコード125を順次実行する。コンパイルコード125は、一つ以上の命令を含み、各命令には、命令種別が付与されている。
メソッド実行部123では、実行対象のメソッドの命令種別に基づいて処理が実行される。
プロセッサ131は、まず、実行対象のメソッドの命令種別がメモリ確保命令であるか否かを判定する(ステップ601)。命令種別がメモリ確保命令でなかった場合には(ステップ601の結果が「NO」)、対象の命令を実行する(ステップ604)。
プロセッサ131は、命令種別がメモリ確保命令であった場合には(ステップ601の結果が「YES」)、メモリ確保部121を実行し、メモリ確保処理を実行する(ステップ602)。メモリ確保処理が終了した後には、メモリ確保が成功したか否かを判定する(ステップ603)。
プロセッサ131は、メモリの確保に失敗した場合には(ステップ603の結果が「NO」)、メソッドの実行を中断し、メモリ不足エラーを発生させる(ステップ605)。
プロセッサ131は、メモリの確保に成功した場合(ステップ603の結果が「YES」)、又は、ステップ604の処理が終了した場合には、次に実行すべき命令があるか否かを判定する(ステップ606)。
プロセッサ131は、次に実行すべき命令がある場合には(ステップ606の結果が「YES」)、ステップ601の処理を実行し、メソッド実行処理を継続する。すべての命令の処理が終了した場合には(ステップ606の結果が「NO」)、メソッド実行処理を終了する。
図14は、本発明の実施の形態のメモリ確保処理602の手順を示すフローチャートである。本処理は、プロセッサ131がメモリ確保部121を処理することによって、実行される。
プロセッサ131は、Javaヒープ領域122に要求された量のメモリを確保可能か否かを判定する(ステップ701)。具体的には、まず、Javaヒープ領域管理テーブル213を参照し、未使用領域先頭3104及び領域終端3105の値を取得する。次に、Javaヒープ領域122のメモリ未使用量を算出し、要求されたメモリ使用量と比較する。
プロセッサ131は、要求された量のメモリがJavaヒープ領域122に確保可能でない場合には(ステップ701の結果が「NO」)、不要なメモリ領域を解放するためにGC処理を実行する(ステップ702)。なお、GC処理の詳細については、図19にて後述する。
プロセッサ131は、GC処理の実行後、Javaヒープ領域122に要求された量のメモリが確保可能か否かを再び判定する(ステップ703)。要求された量のメモリをJavaヒープ領域122に確保できなかった場合には(ステップ703の結果が「NO」)、メモリ確保処理の実行元にメモリ確保に失敗した旨を通知する(ステップ709)。
プロセッサ131は、要求された量のメモリをJavaヒープ領域122に確保可能な場合には(ステップ701又はステップ703の結果が「YES」)、Javaヒープ領域122に要求された量のメモリを確保し、確保されたメモリサイズに基づいて未使用領域先頭3104のアドレスを更新する(ステップ704)。
次に、プロセッサ131は、リークオブジェクトの検出処理を実行するか否かを判定する(ステップ705)。具体的には、Javaヒープ領域管理テーブル213から領域先頭3101及び未使用領域先頭3104を取得し、Javaヒープ領域122のメモリ使用量を算出する。取得されたJavaヒープ領域122のメモリ使用量に基づいて、リークオブジェクト検出管理情報208のリークオブジェクト検出実行条件3002と比較する。
プロセッサ131は、リークオブジェクトの検出処理を実行する場合には(ステップ705の結果が「YES」)、リークオブジェクト検出管理情報208のリークオブジェクト検出実行フラグ3001を“1”に設定する(ステップ707)。リークオブジェクトの検出処理を実行しない場合には(ステップ705の結果が「NO」)、リークオブジェクト検出管理情報208のリークオブジェクト検出実行フラグ3001を“0”に設定する(ステップ706)。
プロセッサ131は、ステップ706の処理又はステップ707の処理が終了すると、メモリ確保処理の実行元に確保されたメモリを通知する(ステップ708)。ステップ708の処理又はステップ709の処理が終了すると、本処理は終了する。
図15は、本発明の実施の形態のページトラップ検出処理の手順を示すフローチャートである。本処理は、プロセッサ131がページトラップ検出部111を処理することによって実行される。ページトラップ検出部111は、JavaVMの実行中に主記憶に常駐させてもよい。
プロセッサ131は、オペレーティングシステム128からページトラップが発生した旨の通知を受けると、ページトラップが発生した領域を判定する(ステップ801)。具体的には、Javaヒープ領域管理テーブル213の領域先頭3101と領域終端3105、及び、外部ヒープ領域管理テーブル214の領域先頭3106と領域終端3108を参照し、受け付けた通知内容に基づいて判定する。
プロセッサ131は、Javaヒープ領域122でページトラップが発生していた場合には(ステップ801の結果が「Javaヒープ領域」)、アクセス領域検査部201を実行することによって、アクセス領域検査処理を開始する(ステップ802)。
プロセッサ131は、外部ヒープ領域110でページトラップが発生していた場合には(ステップ801の結果が「外部ヒープ領域」)、インポート実行部114を実行することによって、インポート処理を開始する(ステップ804)。
プロセッサ131は、Javaヒープ領域122及び外部ヒープ領域110以外の領域でページトラップが発生した場合には(ステップ801の結果が「その他」)、当該ページトラップに対して要求された処理を実行する(ステップ803)。
ステップ802の処理、ステップ803の処理又はステップ804の処理が終了すると、本処理は終了する。
図16は、本発明の実施の形態のアクセス領域検査前処理の手順を示すフローチャートである。本処理は、プロセッサ131がリークオブジェクト検査部206の処理において、メソッド実行前に実行される。
プロセッサ131は、まず、リークオブジェクト検出管理情報208のリークオブジェクト検出実行フラグ3001を参照し、アクセス領域検査を実行するか否かを判定する(ステップ901)。
プロセッサ131は、アクセス領域検査を実行する場合には(ステップ901の結果が「YES」)、リークオブジェクト検出管理情報208のリークオブジェクト検出領域ページ数3003に基づいて、Javaヒープ領域122のリークオブジェクト検出領域3201に対応する領域にページトラップを設定する(ステップ902)。
次に、プロセッサ131は、リークオブジェクト検出管理情報208のオブジェクト整列実行フラグ3006を参照し、GC処理によるオブジェクト再配置の際にオブジェクト整列を実行するか否かを判定する(ステップ903)。
プロセッサ131は、GC処理によるオブジェクト再配置の際にオブジェクト整列を実行する場合には(ステップ903の結果が「YES」)、アクセス領域検査処理で使用されるアクセスアドレステーブル202を作成する(ステップ904)。
アクセス領域検査を実行しない場合(ステップ901の結果が「NO」)、GC処理によるオブジェクト再配置の際にオブジェクト整列を実行しない場合(ステップ903の結果が「NO」)、又はステップ904の処理が終了すると、本処理は終了する。
図17は、本発明の実施の形態のアクセス領域検査処理の手順を示すフローチャートである。本処理は、プロセッサ131がアクセス領域検査部201を処理することによって実行される。
プロセッサ131は、まず、リークオブジェクト検出管理情報208のオブジェクト整列実行フラグ3006を参照し、GC処理におけるオブジェクト再配置の際にオブジェクト整列を実行するか否かを判定する(ステップ1001)。
プロセッサ131は、GC処理におけるオブジェクト再配置の際にオブジェクト整列を実行する場合には(ステップ1001の結果が「YES」)、アクセスアドレス402をアクセスアドレステーブル202に登録する(ステップ1002)。
プロセッサ131は、GC処理によるオブジェクト再配置の際にオブジェクト整列を実行しない場合(ステップ1001の結果が「NO」)、又は、ステップ1002の処理の終了後には、当該アクセスページにおけるアクセス領域検査を終了するか否かを判定する(ステップ1003)。具体的には、アクセスアドレステーブル202の当該アクセスページに対するブロックへの登録数と、リークオブジェクト検出管理情報208のアクセスアドレス収集回数3004とを比較することによって、当該アクセスページにおけるアクセス領域検査を終了するか否かを判定する。
プロセッサ131は、アクセス領域検査処理を終了する場合には(ステップ1003の結果が「YES」)、当該アクセスページのページトラップを解除する(ステップ1004)。アクセスページのページトラップを解除すると、次回のリークオブジェクト検査まで、当該アクセスページにおけるアクセス領域検査を実行しない。こうすることによって、リークオブジェクトの検出処理に伴うメソッド実行中のオーバーヘッドを抑制することができる。
アクセス領域検査処理を終了しない場合(ステップ1003の結果が「NO」)、又はステップ1004の処理が終了すると、本処理は終了する。
図18は、本発明の実施の形態の非アクセスオブジェクトアドレス収集処理の手順を示すフローチャートである。本処理は、プロセッサ131が非アクセスオブジェクトアドレス収集部203を処理することによって実行される。本処理は、リークオブジェクトの検出処理の実行時に、非アクセスオブジェクトアドレス収集処理要求204を受け付けたときに実行される。
プロセッサ131は、まず、リークオブジェクト検出領域3201に未処理の非アクセスページ501が存在するか否かを判定する(ステップ1101)。リークオブジェクト検出領域3201に未処理の非アクセスページ501がある場合には(ステップ1101の結果が「YES」)、当該非アクセスページのページトラップを解除する(ステップ1102)。
次に、プロセッサ131は、ページトラップが解除されたページ内に未処理の非アクセスオブジェクト502が存在するか否かを判定する(ステップ1104)。リークオブジェクト検出領域3201に未処理の非アクセスオブジェクト502がある場合には(ステップ1104の結果が「YES」)、非アクセスオブジェクトアドレステーブル205の非アクセスオブジェクトアドレス3301を参照し、当該オブジェクトのアドレスが登録済みか否かを判定する(ステップ1105)。
プロセッサ131は、当該オブジェクトのアドレスが登録済みの場合には(ステップ1105の結果が「YES」)、当該オブジェクトアドレスに対応する非アクセスオブジェクトアドレステーブル205の非アクセス回数3302の値を“1”増やす(ステップ1106)。
プロセッサ131は、当該オブジェクトのアドレスが登録済みでない場合には(ステップ1105の結果が「NO」)、非アクセスオブジェクトアドレステーブル205の非アクセスオブジェクトアドレス3301に“当該オブジェクトのアドレス”、非アクセス回数3302に“1”を登録する(ステップ1107)。
プロセッサ131は、リークオブジェクト検出領域3201に未処理の非アクセスオブジェクト502が存在しない場合(ステップ1104の結果が「NO」)、ステップ1106の処理の終了後、又はステップ1107の処理の終了後には、ステップ1101の処理を実行し、非アクセスオブジェクトアドレス収集処理を継続する。
プロセッサ131は、リークオブジェクト検出領域3201に未処理の非アクセスページ501が存在しない場合には(ステップ1101の結果が「NO」)、非アクセスオブジェクトアドレステーブル205で更新されていない非アクセスオブジェクトアドレス3301のレコードを削除する(ステップ1103)。ステップ1103の処理が終了すると、本処理は終了する。
図19は、本発明の実施の形態のGC処理702の手順を示すフローチャートである。本処理は、プロセッサ131がGC実行部115を処理することによって実行される。
プロセッサ131は、まず、GC処理を実行するスレッド以外の全スレッドを停止する(ステップ1301)。次に、非アクセスオブジェクトアドレス収集部203を処理することによって、非アクセスオブジェクトアドレス収集処理を実行する(ステップ311)。非アクセスオブジェクトアドレス収集処理は、図18にて前述した処理である。
プロセッサ131は、Javaヒープ領域122を走査しながら、アクセスアドレステーブル202に登録されたアクセスアドレス402に基づいてアクセスオブジェクトアドレス403を取得し、アクセスアドレス402をアクセスオブジェクトアドレス403に置き換える(ステップ1303)。なお、リークオブジェクト検出管理情報208のオブジェクト整列実行フラグ3006に基づいて、アクセスアドレステーブル202にアクセスアドレス402が登録されなかった場合には、ステップ1303の処理では何も処理しない。
プロセッサ131は、オブジェクト種別判定部209を処理することによってオブジェクト種別判定処理を実行し、Javaヒープ領域122に記憶されたすべてのオブジェクトのオブジェクト種別を判定する(ステップ1304)。なお、オブジェクト判定処理の詳細については、図21にて後述する。
プロセッサ131は、再配置アドレス計算部210を処理することによって再配置アドレス計算処理を実行し、ステップ1304の処理で判定されたオブジェクト種別に基づいて、オブジェクトを再配置するアドレスを計算する(ステップ1305)。なお、再配置アドレス計算処理の詳細については、図30にて後述する。
プロセッサ131は、オブジェクト参照更新部211を実行することによって、オブジェクト参照の参照先がステップ1305の処理で計算された参照先オブジェクトの再配置アドレスになるようにオブジェクト参照を更新する(ステップ1306)。
プロセッサ131は、再配置実行部212を処理することによって再配置実行処理を実行し、ステップ1305の処理で計算されたオブジェクトの再配置アドレスにオブジェクトを実際に再配置する(ステップ1307)。なお、再配置実行処理の詳細については、図31にて後述する。
最後に、プロセッサ131は、停止されていたスレッドの実行を再開し(ステップ1308)、本処理を終了する。
図20は、本発明の実施の形態のGC処理702の処理過程において、Javaヒープ領域122及び外部ヒープ領域110の状態を示す図である。図20では、上段にオブジェクト種別判定処理1304の実行後、中段に再配置アドレス計算処理1305の実行後、及び、下段に再配置実行処理1307の実行後の状態を示している。ここでは各状態の概要を説明し、詳細については各処理の手順とともに説明する。
図20の上段に示されたオブジェクト種別判定処理1304の実行後の状態は、Javaヒープ領域122に格納されたオブジェクトにオブジェクト種別が付与されている。なお、“L”はリークオブジェクト、“R”はアクセスオブジェクト、“S”は生存オブジェクトを示している。なお、オブジェクト種別に付随する数字はオブジェクト種別が同じである個々のオブジェクトを識別するために便宜上付加したのものである。アクセスオブジェクトは、リークオブジェクトの検出処理によってアクセスされたと判定されたオブジェクトである。生存オブジェクトは、今回のGC処理702が実行されたリークオブジェクトの検出処理ではアクセスされていないが、最近アクセスされたオブジェクトである。
図20の中段に示された再配置アドレス計算処理1305の実行後の状態は、オブジェクト種別判定処理1304によって各オブジェクトに付与されたオブジェクト種別に基づいて再配置されるアドレスが計算されている。
図20の下段に示された再配置実行処理1307の実行後の状態は、再配置アドレス計算処理1305の計算結果に基づいて、オブジェクトが再配置された後の状態である。
図21は、本発明の実施の形態のオブジェクト種別判定処理の手順を示すフローチャートである。本処理は、プロセッサ131がオブジェクト種別判定部209を処理することによって実行される。
プロセッサ131は、まず、オブジェクトヘッダ3401のオブジェクト種別を“デッド”の状態に初期化する(ステップ1401)。
次に、プロセッサ131は、生存オブジェクトマーキング処理を実行する(ステップ1402)。生存オブジェクトマーキング処理は、生存オブジェクトのオブジェクトヘッダ3401をオブジェクト種別“生存”の状態に設定する。図22に生存オブジェクトマーキング処理1402の終了時点のJavaヒープ領域122及び外部ヒープ領域110の状態を示す。
図22は、本発明の実施の形態のオブジェクト種別判定処理の生存オブジェクトマーキング処理1402の終了時点におけるJavaヒープ領域122及び外部ヒープ領域110に格納されたオブジェクトの状態を示す図である。
各ノードは、オブジェクトを示している。二重丸で示されたオブジェクトは、生存オブジェクトマーキング処理によってオブジェクトヘッダ3401が更新されたオブジェクトである。なお、ノード内の記号は、“S”は生存オブジェクト、“D”はデッドオブジェクトを示している。
また、オブジェクトを連結する矢印は、オブジェクトの参照関係を示している。実線の矢印は、Javaヒープに格納されたオブジェクトに対する参照を示している。点線の矢印は、外部ヒープ領域110に格納されたオブジェクトに対する参照を示している。
ルートセット2001は、プログラム実行環境からアプリケーション実行中に直接参照されるレジスタ、スタック又は静的変数などの領域である。ルートセット2001に保持されるオブジェクト参照を起点として生存オブジェクトマーキング処理が実行されると、ルートセット2001からオブジェクト参照を辿ることによって到達可能なオブジェクトはすべて生存オブジェクトと判定される。
したがって、図22に示すようにプロキシオブジェクト2002及び“S”が付されたオブジェクトはすべて生存オブジェクトである。なお、生存オブジェクトマーキング処理については図26、プロキシオブジェクト2002については図29Aにて後述する。
ここで、図21のオブジェクト種別判定処理のフローチャートの説明に戻る。
プロセッサ131は、非アクセスオブジェクトアドレステーブル205に登録された非アクセスオブジェクトアドレス503によって特定される非アクセスオブジェクトに対して、リークオブジェクト判定処理を実行する。そして、リークオブジェクト判定処理の結果に基づいて、リークオブジェクトと判定された非アクセスオブジェクト502のオブジェクトヘッダ3401にオブジェクト種別“リーク”を設定する(ステップ1403)。図23にステップ1403の処理の終了時点のJavaヒープ領域122及び外部ヒープ領域110の状態を示す。なお、リークオブジェクト判定処理の詳細については、図27にて後述する。
図23は、本発明の実施の形態のオブジェクト種別判定処理のリークオブジェクト判定処理1403の処理の終了時点におけるJavaヒープ領域122及び外部ヒープ領域110に格納されたオブジェクトの状態を示す図である。
二重丸で示されたオブジェクトは、リークオブジェクト判定処理1403によってオブジェクト種別が更新されたオブジェクトである。具体的には、“L”が付され、リークオブジェクトと判定されている。
ここで、図21のオブジェクト種別判定処理のフローチャートの説明に戻る。
次に、プロセッサ131は、ステップ1403の処理によってオブジェクト種別が“リーク”に設定されたリークオブジェクトについて、プロキシオブジェクト登録処理を実行する(ステップ1404)。
プロセッサ131は、リークオブジェクトが生存オブジェクトを参照している場合には、プロキシオブジェクト2002から参照先の生存オブジェクトを参照できるように、参照先の生存オブジェクトのアドレスをプロキシオブジェクト2002に登録する。
リークオブジェクトによって参照されている生存オブジェクトは、便宜上、合流オブジェクトとされる。また、合流オブジェクトの実体は生存オブジェクトであるため、合流オブジェクトのオブジェクトヘッダ3401には、“生存”のオブジェクト種別が設定される。図24にステップ1404の処理の終了時点のJavaヒープ領域122及び外部ヒープ領域110の状態を示す。
図24は、本発明の実施の形態のオブジェクト種別判定処理のプロキシオブジェクト登録処理1404の終了時点におけるJavaヒープ領域122及び外部ヒープ領域110に格納されたオブジェクトの状態を示す図である。“J”が付された二重丸で示されたオブジェクトは、合流オブジェクトを示す。
図24に示す状態では、合流オブジェクト2202及び合流オブジェクト2204が含まれている。オブジェクト2201及びオブジェクト2203は、合流オブジェクト2202及び合流オブジェクト2204を参照するリークオブジェクトである。リークオブジェクト2201及びリークオブジェクト2203は、後述する再配置実行処理1307によって、外部ヒープ領域110に再配置される。
合流オブジェクト2202及び合流オブジェクト2204は、GC処理完了後に、外部ヒープ領域110からJavaヒープ領域122への参照の合流点になる。外部ヒープ領域110に再配置されたリークオブジェクトは、GC処理の対象外となるため、生存オブジェクトマーキング処理1402において、外部ヒープ領域110からJavaヒープ領域122に参照が辿られることはない。したがって、次回のGC処理実行の際に、合流オブジェクト2202及び合流オブジェクト2204から参照を辿ることによって到達可能な生存オブジェクトが誤ってオブジェクト種別“デッド”と判定され、回収されてしまう可能性がある。
プロキシオブジェクト2002は、合流オブジェクト2202及び合流オブジェクト2204を参照するため、GC処理によって誤ってオブジェクトが回収されることを防止できる。プロキシオブジェクト2002を用意することによって、参照関係にあるオブジェクトをGC処理の対象である領域とGC処理の対象外である領域の両方に配置することができる。なお、プロキシオブジェクト登録処理1404の詳細については、図28にて後述する。
ここで、図21のオブジェクト種別判定処理のフローチャートの説明に戻る。
最後に、プロセッサ131は、アクセスアドレステーブル202に登録されたアクセスオブジェクトアドレス403によって特定されるアクセスオブジェクト404のオブジェクトヘッダ3401にオブジェクト種別“アクセス”を設定する(ステップ1405)。ステップ1405の処理が終了すると、本処理は終了する。図25にステップ1405の処理の終了時点のJavaヒープ領域122及び外部ヒープ領域110の状態を示す。
図25は、本発明の実施の形態のオブジェクト種別判定処理の終了時点におけるJavaヒープ領域122及び外部ヒープ領域110に格納されたオブジェクトの状態を示す図である。
二重丸で示されたオブジェクトは、ステップ1405の処理によってオブジェクト種別が更新されたオブジェクトである。具体的には、“A”が付されたアクセスオブジェクトである。アクセスオブジェクトであるか否かは、前述のようにアクセスアドレステーブル202に登録された情報に基づいて判定される。
また、オブジェクト種別判定処理が終了すると、Javaヒープ領域122に格納されたオブジェクトのオブジェクト種別は図20の上段に示すよう判別可能になる。なお、図20の上段に示すように、オブジェクトが互いに隙間なく配置されるか否かはメモリ管理部124のメモリ管理方針に依存する。本発明の実施の形態では、図20の上段に示すように、オブジェクトを互いに隙間なく配置させる。
図26は、本発明の実施の形態のオブジェクト種別判定処理における生存オブジェクトマーキング処理の手順を示すフローチャートである。本処理は、Javaヒープ領域122に格納された生存オブジェクトのオブジェクトヘッダ3401に“生存”のオブジェクト種別を設定する。また、本処理の対象は、ルートセット2001から到達可能なJavaヒープ領域122に格納されたオブジェクトである。
プロセッサ131は、まず、処理対象のオブジェクトのオブジェクト参照に未処理のオブジェクト参照が存在するか否かを判定する(ステップ1501)。
プロセッサ131は、未処理のオブジェクト参照が存在する場合には(ステップ1501の結果が「YES」)、参照先のオブジェクトが外部ヒープ領域110に格納されているか否かを判定する(ステップ1502)。具体的には、外部ヒープ領域管理テーブル214の領域先頭3106及び領域終端3108を参照し、オブジェクト参照の参照先のアドレスと比較する。外部ヒープ領域110に格納されたオブジェクトはリークオブジェクトであるため、本処理の対象となるオブジェクトでない。ステップ1502の処理は、参照先のオブジェクトが本処理の対象であるか否かを判定する。
プロセッサ131は、参照先のオブジェクトが外部ヒープ領域110に格納されていない場合には(ステップ1502の結果が「NO」)、参照先のオブジェクトを新たに処理対象とする(ステップ1503)。
次に、プロセッサ131は、新たに処理対象となったオブジェクトのオブジェクトヘッダ3401を参照し、オブジェクト種別が“デッド”であるか否かを判定する(ステップ1504)。なお、本処理の開始前に、Javaヒープ領域122に格納されたオブジェクトのオブジェクト種別は、すべて“デッド”に初期化されている(図21のステップ1401)。
プロセッサ131は、オブジェクト種別が“デッド”である場合には(ステップ1504の結果が「YES」)、オブジェクトヘッダ3401にオブジェクト種別“生存”を設定する(ステップ1505)。
プロセッサ131は、処理対象のオブジェクトの参照先オブジェクトに対して生存オブジェクトマーキング処理を再帰的に実行する(ステップ1402)。
プロセッサ131は、オブジェクト種別が“デッド”でない場合(ステップ1504の結果が「NO」)、又はステップ1506の処理の終了後には、処理対象のオブジェクトの参照元オブジェクトを新たに処理対象のオブジェクトとする(ステップ1507)。
プロセッサ131は、参照先のオブジェクトが外部ヒープ領域110に格納されている場合(ステップ1502の結果が「YES」)、又はステップ1507の処理の終了後には、ステップ1501の処理に戻る。そして、未処理のオブジェクトに対して生存オブジェクトマーキング処理1402の実行を継続する。
プロセッサ131は、未処理のオブジェクト参照が存在しない場合には(ステップ1501の結果が「NO」)、すべての処理対象のオブジェクトに対する生存オブジェクトマーキング処理が完了したため、本処理を終了する。
図27は、本発明の実施の形態のリークオブジェクト判定処理の手順を示すフローチャートである。リークオブジェクト判定処理は、処理対象のオブジェクトがリークオブジェクトであるか否かを判定する。本処理は、プロセッサ131がリークオブジェクト判定部207を処理することによって実行される。
プロセッサ131は、まず、処理対象のオブジェクトがリークオブジェクトに該当するか否かを判定する(ステップ1601)。具体的には、非アクセスオブジェクトアドレステーブル205を参照し、処理対象のオブジェクトの非アクセス回数3302とリークオブジェクト検出管理情報208のリークオブジェクト条件3005とを比較する。
プロセッサ131は、処理対象のオブジェクトがリークオブジェクトの条件を満たしている場合には(ステップ1601の結果が「YES」)、当該オブジェクトがリークオブジェクトである旨を本処理の実行元に通知する(ステップ1602)。実行元の処理において、処理対象のオブジェクトのオブジェクト種別を“リーク”に更新する(図21のステップ1403)。
プロセッサ131は、処理対象のオブジェクトがリークオブジェクトの条件を満たしていない場合には(ステップ1601の結果が「NO」)、当該オブジェクトが非リークオブジェクトである旨を本処理の実行元に通知する(ステップ1603)。
ステップ1602の処理又はステップ1603の処理の終了後、本処理は終了する。
図28は、本発明の実施の形態のプロキシオブジェクト登録処理の手順を示すフローチャートである。プロキシオブジェクト登録処理は、リークオブジェクトに参照された生存オブジェクトをプロキシオブジェクトに登録する処理である。本処理は、リークオブジェクトに対して実行される。
プロセッサ131は、まず、処理対象のオブジェクトのオブジェクト参照で未処理のオブジェクト参照が存在するか否かを判定する(ステップ1701)。
プロセッサ131は、未処理のオブジェクト参照が存在する場合には(ステップ1701の結果が「YES」)、当該オブジェクト参照の参照先が外部ヒープ領域110であるか否かを判定する(ステップ1702)。具体的には、図26のステップ1502の処理と同じく、外部ヒープ領域管理テーブル214の領域先頭3106及び領域終端3108を参照し、オブジェクト参照の参照先のアドレスと比較する。外部ヒープ領域110に格納されたオブジェクトはリークオブジェクトであるため、本処理の対象となるオブジェクトでない。ステップ1702の処理は参照先のオブジェクトが本処理の対象であるか否かを判定する。
プロセッサ131は、参照先のオブジェクトが外部ヒープ領域110に格納されていない場合には(ステップ1702の結果が「NO」)、参照先オブジェクトが生存オブジェクトであるか否かを判定する(ステップ1703)。具体的には、参照先オブジェクトのオブジェクトヘッダ3401に格納されたオブジェクト種別を参照し、オブジェクト種別が“生存”であるか否かを判定する。
プロセッサ131は、参照先オブジェクトが生存オブジェクトである場合には(ステップ1703の結果が「YES」)、参照先オブジェクトのアドレスをプロキシオブジェクト2002が保持する未登録のオブジェクト参照に登録する。さらに、登録されたプロキシオブジェクト2002が保持するオブジェクト参照の識別子を取得する。そして、当該識別子を処理対象のオブジェクトのオブジェクト参照に記録する(ステップ1704)。ここで、図29Aを参照しながらプロキシオブジェクトの構造を説明し、さらに、ステップ1704の処理を、具体例を示しながら説明する。
図29Aは、本発明の実施の形態のプロキシオブジェクト2002の構造を示す図である。
プロキシオブジェクト2002は、複数のオブジェクト参照を格納可能である。プロキシオブジェクト2002に格納されるオブジェクト参照には、合流オブジェクトのアドレスが格納される。
また、オブジェクトが保持するオブジェクト参照3601は、オブジェクトデータ3402に格納され、オブジェクトが保持するオブジェクト参照3601の各フィールドは、識別子3602によって識別される。本発明の実施の形態では、オブジェクト参照を配列として管理しているため、識別子3602はオブジェクト参照配列のインデックスとなる。
プロキシオブジェクト2002は、本発明の実施の形態において、言語処理システムがオブジェクトの参照関係を管理するためのオブジェクトであって、基本的にはオブジェクト参照のフィールドのみを有する。
プロキシオブジェクトが保持するオブジェクト参照3603の各フィールドは、プロキシオブジェクトが保持するオブジェクト参照の識別子3604によって識別される。また、プロキシオブジェクトが保持するオブジェクト参照3603の各フィールドは、オブジェクト参照更新部211によるオブジェクト参照更新処理の対象である。そして、プロキシオブジェクトが保持するオブジェクト参照3603によって特定されるオブジェクトがGC処理702によって再配置されると、プロキシオブジェクトが保持するオブジェクト参照3603が保持するアドレスも更新される。
プロキシオブジェクト2002は、ルートセット2001から参照されていれば、Javaヒープ領域122以外の領域に配置してもよい。なお、本発明の実施の形態では、プロキシオブジェクト2002をJavaヒープ領域122に配置する。
プロキシオブジェクト2002は、ルートセット2001から参照されているため、JavaVM109が終了するまで回収されることはない。一方、アプリケーションプログラムを実行中にJavaヒープ領域122及び外部ヒープ領域110に空き領域がなくなった状態でプロキシオブジェクト2002がJavaヒープ領域122に配置されている場合には、Javaヒープ領域122の空き領域を増やす目的でプロキシオブジェクト2002を回収してもよい。なお、プロキシオブジェクト2002を回収する場合には、オブジェクトのインポート処理を実行することができなくなるため、プロキシオブジェクト2002を回収する前にインポート処理の実行を禁止する必要がある。
続いて、ステップ1704の処理について説明する。処理対象のオブジェクトには、三つのオブジェクト参照が含まれている。オブジェクト参照は、#0、#1及び#2の識別子3602が付与されている。また、識別子3602が“#1”であるオブジェクト参照3605は、オブジェクト3607を参照している。以上の状態を初期状態とする。
以上説明した初期状態に対してステップ1704の処理が実行されると、まず、プロキシオブジェクトが保持するオブジェクト参照の識別子3604が“#3”であるオブジェクト参照3606は、オブジェクト3607を参照するように更新される。さらに、処理対象のオブジェクトが保持するオブジェクト参照の識別子3602が“#1”であるオブジェクト参照3605は、プロキシオブジェクトが保持するオブジェクト参照の識別子3604が“#3”であるオブジェクト参照3606を参照するように更新される。なお、オブジェクトが保持するオブジェクト参照3601は、オブジェクトアドレスを直接保持する場合とプロキシオブジェクトが保持するオブジェクト参照の識別子3604を保持する場合がある。
これに対し、図7にて説明したように、オブジェクトへのポインタの下位数ビットは0となるため、本発明の実施の形態では、最下位ビットの状態によって、オブジェクト参照がオブジェクトアドレスとプロキシオブジェクトが保持するオブジェクト参照の識別子3604のいずれを保持しているのかを判定することができる。図29Bに32ビット環境においてオブジェクト参照が保持する値の例を示す。
図29Bは、本発明の実施の形態の32ビット環境におけるオブジェクト参照に保持される値の一例を示す図である。
図29Bの上段に示すようにオブジェクト参照に保持された値の最下位ビットが“0”の場合には、オブジェクトアドレスそのものがオブジェクト参照に保持されている。
一方、図29Bの下段に示すようにオブジェクト参照に保持された値の最下位ビットが“1”の場合には、プロキシオブジェクトが保持するオブジェクト参照の識別子3604がオブジェクト参照に保持されている。具体的には、オブジェクト参照のフィールドの上位31ビットに保持されており、オブジェクト参照のフィールドからプロキシオブジェクトが保持するオブジェクト参照の識別子3604を取り出す場合には、オブジェクト参照のフィールドの値を1ビット右論理シフトした値をプロキシオブジェクトが保持するオブジェクト参照の識別子3604として取り出す。また、オブジェクト参照のフィールドにプロキシオブジェクトが保持するオブジェクト参照の識別子3604を記録する場合には、プロキシオブジェクトが保持するオブジェクト参照の識別子3604の値を1ビット左論理シフトし、最下位ビットを“1”とした値を記録する。
なお、プロキシオブジェクト2002がアドレス空間に対して固定されて配置されている場合には、プロキシオブジェクトが保持するオブジェクト参照の識別子3604の代わりに、プロキシオブジェクトが保持するオブジェクト参照のフィールドのアドレスをオブジェクトが保持するオブジェクト参照3601に記録してもよい。プロキシオブジェクト2002が配置された領域の範囲によって、オブジェクト参照がオブジェクトアドレス又はプロキシオブジェクトが保持するオブジェクト参照の識別子3604のいずれかを保持しているのかを判定することが可能である。
ここで、図28のプロキシオブジェクト登録処理1404のフローチャートの説明に戻る。
プロセッサ131は、参照先が外部ヒープ領域110である場合(ステップ1702の結果が「YES」)、オブジェクト種別が“生存”でない場合(ステップ1703の結果が「NO」)、又はステップ1704の処理の終了後は、ステップ1701の処理に戻り、プロキシオブジェクト登録処理を継続する。
未処理のオブジェクト参照が存在しなくなると(ステップ1701の結果が「NO」)、本処理は終了する。
図30は、本発明の実施の形態の再配置アドレス計算処理の手順を示すフローチャートである。本処理は、プロセッサ131が再配置アドレス計算部210を処理することによって実行される。
プロセッサ131は、アクセスオブジェクトの配置領域を決定する(ステップ1801)。具体的には、まず、Javaヒープ領域管理テーブル213の生存領域終端3102に領域先頭3101のアドレスを設定する。さらに、Javaヒープ領域122に格納されたアクセスオブジェクトの合計サイズを求め、未使用領域先頭3104に領域先頭3101のポインタを求められた合計サイズだけ加算されたアドレスを設定する。
プロセッサ131は、Javaヒープ領域122に配置されたオブジェクトを順に走査し、未処理のオブジェクトが存在するか否かを判定する(ステップ1802)。
プロセッサ131は、未処理のオブジェクトが存在する場合には(ステップ1802の結果が「YES」)、処理対象のオブジェクトのオブジェクトヘッダ3401を参照し、オブジェクト種別を判定する(ステップ1803)。本発明の実施の形態では、オブジェクトの種別によって、配置する領域が決定される。具体的には、図20の中段に示したように、生存オブジェクトは生存オブジェクト配置領域1201に配置し、アクセスオブジェクトはアクセスオブジェクト配置領域1202に配置する。
プロセッサ131は、処理対象のオブジェクトのオブジェクト種別が“生存”と判定された場合には(ステップ1803の結果が「生存」)、図20の中段に示したように、当該オブジェクトがJavaヒープ領域122の生存オブジェクト配置領域1201に配置されるように再配置アドレスを計算する(ステップ1805)。
なお、生存オブジェクトの再配置アドレスは、Javaヒープ領域管理テーブル213の生存領域終端3102のポインタによって特定されるアドレスであって、再配置アドレスの計算後には、生存領域終端3102のポインタを生存オブジェクトのサイズだけ加算しながら再配置アドレスの計算を継続する。
プロセッサ131は、処理対象のオブジェクトのオブジェクト種別が“アクセス”と判定された場合には(ステップ1803の結果が「アクセス」)、図20の中段に示したように、当該オブジェクトがJavaヒープ領域122のアクセスオブジェクト配置領域1202に配置されるように再配置アドレスを計算する(ステップ1805)。
なお、アクセスオブジェクトの再配置アドレスはJavaヒープ領域管理テーブル213の未使用領域先頭3104のポインタによって特定されるアドレスであって、再配置アドレスの計算後、未使用領域先頭3104に領域のポインタを当該アクセスオブジェクトのサイズだけ加算しながら再配置アドレスの計算を継続する。
プロセッサ131は、処理対象のオブジェクトのオブジェクト種別が“リーク”と判定された場合には(ステップ1803の結果が「リーク」)、図20の中段に示したように、当該オブジェクトが外部ヒープ領域110に再配置されるように再配置アドレスを計算する(ステップ1804)。
なお、リークオブジェクトの再配置アドレスは外部ヒープ領域管理テーブル214の未使用領域先頭3107のポインタによって指し示されるアドレスであって、再配置アドレスの計算後、未使用領域先頭3107に領域のポインタを当該リークオブジェクトのサイズだけ加算しながら再配置アドレスの計算を継続する。
プロセッサ131は、処理対象のオブジェクトのオブジェクト種別が“デッド”と判定された場合(ステップ1803の結果が「デッド」)、又はステップ1804から1806の処理の終了後には、ステップ1802に戻り、再配置アドレス計算処理を継続する。未処理のオブジェクトが存在しない場合には(ステップ1802の結果が「NO」)、本処理は終了する。
ここで、オブジェクトのサイズは、通常、ページサイズと比較して小さく、1ページに複数のオブジェクトが配置される。また、ページトラップは、通常、ページ単位でのみ設定及び解除が可能である。そのため、メソッド実行中に頻繁にアクセスされるオブジェクトと、アクセス頻度の低いオブジェクトが同一ページに配置されている場合には、頻繁にアクセスされるオブジェクトにアクセスされたときに、当該ページに設定されたページトラップが解除されてしまうため、アクセス頻度の低いオブジェクトを検出するのは困難になってしまう。
そこで、以上の問題を回避するために、ステップ1805及びステップ1806の処理では、生存オブジェクトとアクセスオブジェクトとがJavaヒープ領域122の異なる領域に配置され、極力同一ページに配置されないように再配置アドレスを計算している。また、このように再配置を繰り返すことで、Javaヒープ領域122のオブジェクトは、アクセス傾向に応じて整列されていくため、メソッド実行中にアクセス頻度の低いオブジェクトの検出が容易になり、リークオブジェクトの検出精度をより向上させることができる。
図31は、本発明の実施の形態の再配置実行処理の手順を示すフローチャートである。本処理は、プロセッサ131が再配置実行部212を処理することによって実行される。
プロセッサ131は、まず、外部ヒープ領域110に設定されたページトラップを解除し、外部ヒープ領域110にリークオブジェクトを配置可能な状態にする(ステップ1901)。
プロセッサ131は、Javaヒープ領域122に配置されたオブジェクトを順に走査し、未処理のオブジェクトが存在するか否かを判定する(ステップ1902)。
プロセッサ131は、未処理のオブジェクトが存在する場合には(ステップ1902の結果が「YES」)、再配置アドレス計算処理によって算出された再配置アドレスに当該オブジェクトを配置する(ステップ1904)。ステップ1904の処理が終了すると、ステップ1902の処理を実行し、再配置実行処理を継続する。
なお、外部ヒープ領域110としてファイル105が使用され、ファイルオフセットマップ217を使用して主記憶と別に管理されている場合には、図9にて説明したように、Javaヒープ領域122から外部ヒープ領域110にリークオブジェクトを再配置する。
プロセッサ131は、未処理のオブジェクトが存在しない場合には(ステップ1902の結果が「NO」)、外部ヒープ領域110にページトラップを設定し、メソッド実行時のリークオブジェクトへのアクセスを検知可能な状態にする(ステップ1903)。ステップ1903の処理の終了後、本処理は終了する。
ここで、ステップ1903の処理の終了時点におけるJavaヒープ領域122に格納されたオブジェクト119と外部ヒープ領域110に格納されたリークオブジェクト112の参照関係を図32に示す。
図32は、本発明の実施の形態の再配置実行処理終了後におけるJavaヒープ領域122及び外部ヒープ領域110に格納されたオブジェクトの状態を示す図である。
図32は、通常のGC処理によってデッドオブジェクトが回収され、さらに、オブジェクト種別が“リーク”であるリークオブジェクトがJavaヒープ領域122から外部ヒープ領域110に再配置された状態を示している。このようにリークオブジェクトをJavaヒープ領域122から外部ヒープ領域110に移動させることによって、Javaヒープ領域122の空き領域を増やすことができる。
また、再配置後のオブジェクトの配置は、図20の下段に示した配置となる。図20の上段に示したようにJavaヒープ領域122に配置されていたオブジェクトは、再配置アドレスの計算後、図20の下段に示したように再配置され、不要なオブジェクト(デッドオブジェクト)が回収される。
図33は、本発明の実施の形態のインポート処理の手順を示すフローチャートである。本処理は、プロセッサ131がインポート実行部114を処理することによって実行される。
プロセッサ131は、まず、Javaヒープ領域122又は外部ヒープ領域110に格納されたオブジェクトが移動されないように、インポート処理を実行するスレッド以外の全スレッドを停止する(ステップ2501)。
プロセッサ131は、Javaヒープ領域122に設定されたページトラップを解除し、Javaヒープ領域122のオブジェクト119をアクセス可能な状態にする(ステップ2502)。
プロセッサ131は、外部ヒープ領域110に設定されたページトラップを解除し、外部ヒープ領域110のリークオブジェクト112にアクセス可能な状態にする(ステップ2503)。
プロセッサ131は、Javaヒープ領域122に格納されたオブジェクト119を順に走査し、メソッド実行時にアクセスされたオブジェクトを参照している参照元オブジェクトを探索する。参照元オブジェクトが見つかった場合には、Javaヒープ領域管理テーブル213の未使用領域先頭3104を取得し、当該オブジェクトの再配置アドレスとする。そして、参照元オブジェクトに保持される当該オブジェクトへのオブジェクト参照を取得された再配置アドレスに更新する(ステップ2504)。
プロセッサ131は、外部ヒープ領域110のリークオブジェクト112を順に走査し、アクセスされたオブジェクトを参照している参照元リークオブジェクトを探索する。参照元リークオブジェクトが見つかった場合には、ステップ2504の処理で取得された再配置アドレスをプロキシオブジェクト2002が保持する未登録のオブジェクト参照に登録し、プロキシオブジェクトが保持するオブジェクト参照の識別子3604を取得する。そして、参照元リークオブジェクトに保持される当該オブジェクトへのオブジェクト参照に前述した識別子3604を記録する(ステップ2505)。
プロセッサ131は、アクセスされたオブジェクトを再配置アドレスに再配置し、Javaヒープ領域管理テーブル213の未使用領域先頭3104のポインタを当該オブジェクトのサイズだけ加算する(ステップ2506)。なお、外部ヒープ領域110としてファイル105が使用され、ファイルオフセットマップ217を使用して主記憶と別に管理されている場合には、図9にて説明したように、外部ヒープ領域110からJavaヒープ領域122にオブジェクトを再配置する。
次に、プロセッサ131は、参照解決処理を実行し、当該オブジェクトのオブジェクト参照を解決する(ステップ2507)。参照解決処理とは、アクセスされたオブジェクトが、Javaヒープ領域122から外部ヒープ領域110に再配置される前に参照していたオブジェクトを、当該オブジェクトが外部ヒープ領域110からJavaヒープ領域122に再配置された後でも正しく参照するように、当該オブジェクトのオブジェクト参照を更新する処理である。
GC処理が実行されるとJavaヒープ領域122に格納されたオブジェクトは、再配置される。一方、本発明の実施の形態のように、外部ヒープ領域110をGC処理の対象から除外していると、外部ヒープ領域110に格納されたリークオブジェクトのオブジェクト参照は更新されず、本来参照するべきオブジェクトが参照されなくなる場合がある。参照解決処理により、GC処理の実行対象でないオブジェクトのオブジェクト参照の整合性を確保することができるため、外部ヒープ領域110をGC処理の対象から除外することができる。なお、参照解決処理の詳細については、図34にて説明する。
図34は、本発明の実施の形態のインポート処理における参照解決処理の手順を示すフローチャートである。
プロセッサ131は、処理対象オブジェクトが保持するオブジェクト参照が、プロキシオブジェクト2002が保持するオブジェクト参照の識別子3604を格納しているか否かを判定する(ステップ2601)。なお、処理対象オブジェクトが保持するオブジェクト参照が、プロキシオブジェクト2002が保持するオブジェクト参照の識別子3604を格納しているか否かは、図29Bに示したように、オブジェクト参照の最下位ビットの値を検査することによって判定可能である。
プロセッサ131は、プロキシオブジェクト2002に格納されたオブジェクト参照の識別子3604が、処理対象オブジェクトの未処理のオブジェクト参照に含まれる場合には(ステップ2601の結果が「YES」)、プロキシオブジェクト2002の対応するオブジェクト参照からオブジェクトアドレスを取得し、未処理の対象オブジェクトのオブジェクト参照に代入する。さらに、プロキシオブジェクト2002の対応するオブジェクト参照の値にNULL値を代入し、未登録状態とする(ステップ2602)。なお、ステップ2602の処理は、図28のプロキシオブジェクト登録処理のステップ1704の処理と逆の処理となる。
プロセッサ131は、ステップ2602の処理の終了後、ステップ2601に戻り、参照解決処理を継続する。処理対象オブジェクトが保持するオブジェクト参照が、プロキシオブジェクト2002が保持するオブジェクト参照の識別子3604を格納していない場合には(ステップ2601の結果が「NO」)、参照解決処理を終了する。
ここで、参照解決処理の終了時点におけるJavaヒープ領域122のオブジェクト119と外部ヒープ領域110のリークオブジェクト112の参照関係を図35に示す。
図35は、本発明の実施の形態の参照解決処理終了後におけるJavaヒープ領域122及び外部ヒープ領域110に格納されたオブジェクトの状態を示す図である。
図35では、図32に示された状態から、外部ヒープ領域110に格納されていたオブジェクト2701がアクセスされた場合を示している。このとき、インポート実行管理情報218のインポート範囲3008の値には“1”が設定されている。したがって、直接アクセスされたオブジェクト2701と、直接アクセスされたオブジェクト2701のオブジェクト参照を1段辿ることによって到達可能なオブジェクト2702までがインポート処理によって、外部ヒープ領域110からJavaヒープ領域122に再配置される。なお、直接アクセスされたオブジェクト2701のオブジェクト参照を2段辿らないと到達不可能なオブジェクト2703は、インポート処理の対象となっていないため、引き続き外部ヒープ領域110に格納される。
ここで、図33のインポート処理のフローチャートの説明に戻る。
プロセッサ131は、外部ヒープ領域110にページトラップを設定し、メソッド実行時の外部ヒープ領域110に格納されたオブジェクトに対するアクセスを検知可能な状態にする(ステップ2508)。最後に、停止していたスレッドの実行を再開し(ステップ2509)、本処理を終了する。
インポート処理によって、外部ヒープ領域110からJavaヒープ領域122にオブジェクトが再配置されると、再配置されたオブジェクトが配置してあった領域は再利用できない空き領域となる。通常、外部ヒープ領域110からJavaヒープ領域122に再配置されるオブジェクトは少ないため、前述の空き領域による外部ヒープ領域110の使用効率の低下は大きな問題にはならない。
しかし、JavaVM109を長時間連続して実行する場合など、外部ヒープ領域110の空き領域が蓄積されることによって、外部ヒープ領域110の使用効率の低下が無視できなくなる可能性がある。特に、外部ヒープ領域110に空き領域がなくなった場合には、外部ヒープ領域110を対象とするGC処理を実行し、外部ヒープ領域110の使用効率を改善する必要がある。
なお、本発明の実施の形態では、外部ヒープ領域110を対象とするGC処理が必要になった場合に、Javaヒープ領域122を対象とするGC処理を実行し、Javaヒープ領域122を対象とするGC処理の延長として外部ヒープ領域110を対象とするGC処理を実行する。以下、図36を参照し、図19に示したJavaヒープ領域122を対象とするGC処理を引用しながら外部ヒープ領域110を対象とするGC処理について説明する。
図36は、本発明の実施の形態の外部ヒープ領域110を対象とするGC処理の手順を示すフローチャートである。
プロセッサ131は、外部ヒープ領域110に格納されたオブジェクトについて、オブジェクトヘッダ3401のオブジェクト種別ビットを“デッド”の状態で初期化する(ステップ2801)。ステップ2801の処理は、図21のステップ1401の処理の際に実行される。
次に、プロセッサ131は、外部ヒープ領域110に格納されたリークオブジェクト112についても生存オブジェクトマーキング処理を実行する(ステップ2802)。具体的には、外部ヒープ領域110に格納されたリークオブジェクト112については、図26のステップ1502の判定処理の代わりに、当該オブジェクト参照の参照先がJavaヒープ領域122であるか否かを判定する。ステップ2802の処理は、図21のステップ1402の処理の際に実行される。
なお、本発明の実施の形態では、プロキシオブジェクト登録処理においてステップ1704の処理が実行されているため、当該オブジェクト参照の参照先がJavaヒープ領域122であるか否かの判定は、プロキシオブジェクトのオブジェクト参照の識別子3604を保持しているか否かの判定と同じである。
プロセッサ131は、ステップ2802の処理で生存オブジェクトと判定されなかった外部ヒープ領域110に含まれるデッドオブジェクトについて、プロキシオブジェクト登録解除処理を実行する(ステップ2803)。プロキシオブジェクト登録解除処理を実行することによって、プロキシオブジェクト2002を介して処理対象のデッドオブジェクトからのみ参照され、他のオブジェクトと参照関係にない生存オブジェクトをGC処理によって回収することができる。なお、プロキシオブジェクト登録解除処理の詳細については、図37にて後述する。また、デッドオブジェクトを指し示していたファイルオフセットマップ217のオブジェクトアドレス3701をNULL値に更新する。
図37は、本発明の実施の形態の外部ヒープ領域110を対象とするGC処理におけるプロキシオブジェクト登録解除処理の手順を示すフローチャートである。本処理は、図36のステップ2802の処理でデッドオブジェクトと判定された外部ヒープ領域110に含まれるオブジェクトに対して実行される。
プロセッサ131は、プロキシオブジェクト2002に格納されたオブジェクト参照の識別子が、処理対象オブジェクトの未処理のオブジェクト参照に含まれるか否かを判定する(ステップ2901)。
プロセッサ131は、プロキシオブジェクト2002に格納されたオブジェクト参照の識別子が、処理対象オブジェクトの未処理のオブジェクト参照に含まれる場合には(ステップ2901の結果が「YES」)、プロキシオブジェクト2002の対応するオブジェクト参照の値にNULL値を代入し、未登録状態とする(ステップ2902)。プロキシオブジェクト2002からの参照を解除することによって、他のオブジェクトから参照されていなければ、参照を解除されたオブジェクトをGC処理によって回収することができる。
プロセッサ131は、ステップ2902の処理の終了後、ステップ2901に戻り、参照解決処理を継続する。プロキシオブジェクト2002に格納されたオブジェクト参照の識別子が、処理対象オブジェクトの未処理のオブジェクト参照に含まれない場合には(ステップ2901の結果が「NO」)、本処理を終了する。
ここで、図36の外部ヒープ領域110を対象とするGC処理のフローチャートの説明に戻る。
プロセッサ131は、ファイルオフセットマップ217に含まれるオブジェクトアドレス3701がNULL値であるレコードを削除し、ファイルオフセットマップ217をメンテナンスする(ステップ2804)。
プロセッサ131は、外部ヒープ領域110に含まれるリークオブジェクト112を対象として、再配置アドレス計算処理を実行し、オブジェクト種別が“生存”であるオブジェクトが、外部ヒープ領域110の領域に無駄なく再配置されるように再配置アドレスを計算する(ステップ2805)。ステップ2805の処理は、図19のステップ1305の処理の際に実行される。
プロセッサ131は、ステップ2805の処理で計算された参照先オブジェクトの再配置アドレスに基づいて、各オブジェクトのオブジェクト参照の値を更新する(ステップ2806)。ステップ2806の処理は、図19のステップ1306の処理の際に実行される。ステップ2806の処理について、図38Aから図38Cを用いて説明する。
図38Aは、本発明の実施の形態のファイルオフセットマップ217を利用したオブジェクトの参照について説明する図である。
図38Aを参照すると、Javaヒープ領域122に格納されたオブジェクトのオブジェクト参照3801が、外部ヒープ領域110内の仮想的なオブジェクト3802を参照している。すなわち、オブジェクト参照3801には、仮想的なオブジェクト3802の論理アドレスが格納されている。
また、ファイルオフセットマップ217は、図9に示したように、オブジェクトアドレス3701に仮想的なオブジェクト3802の論理アドレスを格納し、ファイルオフセット3702にファイル105のファイルオフセットを格納している。
仮想的なオブジェクト3802の実体3803は、ファイル105に記録され、ファイルオフセットマップ215に格納された情報に基づいて、仮想的なオブジェクト3802の論理アドレスに対応するファイルオフセット3702の位置に配置される。
図38Bは、本発明の実施の形態のファイルオフセットマップ217を利用したオブジェクトの参照について説明する図であって、オブジェクト参照の値が更新された状態を示す図である。
図38Bは、図36のステップ2806の処理によって、外部ヒープ領域に格納された仮想的なオブジェクトが再配置され、論理アドレスが変更された状態である。このとき、Javaヒープ領域122に含まれるオブジェクトに格納されたオブジェクト参照3801が更新されている。
具体的には、ステップ2806の処理によって、仮想的なオブジェクト3802は仮想的なオブジェクト3804として再配置され、オブジェクト参照3801及びオブジェクトアドレス3701も仮想的なオブジェクト3804を指し示す。なお、この段階では、ファイル105に格納されたオブジェクトの実体はそのままの状態である。
ここで、図36の外部ヒープ領域110を対象とするGC処理のフローチャートの説明に戻る。
プロセッサ131は、ファイル105の先頭から順にファイルオフセットマップ217のファイルオフセット3702に対応するオブジェクトの実体を再配置する(ステップ2807)。ステップ2807の処理を図38Cを用いて説明する。ステップ2807の処理が終了すると、外部ヒープ領域110を対象とするGC処理は終了する。
図38Cは、本発明の実施の形態のファイルオフセットマップ217を利用したオブジェクトの参照について説明する図であって、オブジェクトが再配置された状態を示す図である。仮想的なオブジェクト3804の実体3803は、ステップ2807の処理によって、実体3805の位置に再配置されている。
なお、ファイルオフセットマップ217を利用することによって、オブジェクトに含まれるオブジェクト参照の値を変更せずにオブジェクトの実体の配置を変更することができるため、ステップ2807の処理はメソッド実行と並行して実行することができる。したがって、ステップ2801からステップ2806までのフェーズ1の処理はJavaヒープ領域122に対するGC処理とともに実行する必要があるが、ステップ2807のフェーズ2の処理については、GC処理が完了する前に全スレッドの実行を再開してもよい。
図39は、本発明の実施の形態のJavaVM109によって出力装置130に出力されるGC処理及びインポート処理のログの一例を示す図である。以下、出力されたログの各フィールドについて説明する。
フィールド3901は、当該ログについての情報を示すフィールドである。“G”は、GC処理についてのログであることを示す。また、“I”は、インポート処理についてのログであることを示している。図39の例では、“G”によってGC処理についてのログであること、“#3”によってJavaVM109が起動してから通算3回目のGC処理のログであること、“(24.889)”によってJavaVM109が起動してから24.889秒後に実行されたGC処理のログであることを表している。
フィールド3902は、フィールド3901で示した処理に要した時間を示す。図39の例では、当該GC処理に0.522876秒を要したことが示されている。
フィールド3903は、当該行に示される情報がいずれの領域に関する情報であるかを示す。具体的には、“<JH>”は、Javaヒープ領域122についての情報、“<EH>”は、外部ヒープ領域110についての情報、“<HD>”は、補助記憶102についての情報であることを示している。
フィールド3904は、フィールド3901に示された処理によって、フィールド3903に示された領域の使用量の変化を示す。図39の例では、GC処理によってJavaヒープ領域122の使用量が“185227K”から“123427K”に変化したことを示している。
フィールド3905は、フィールド3903に示された領域のサイズを示す。図39の例では、Javaヒープ領域122のサイズが“262144K”であることを表している。
利用者は、出力されたGC処理及びインポート処理のログを参照することによって、GC処理及びインポート処理の実行時間及びJavaヒープ領域などの利用状況を把握することができる。
図40は、本発明の実施の形態のJavaVM109によって出力装置130に出力されるオブジェクト統計情報の一例を示す図である。以下、出力されたオブジェクト統計情報の各フィールドについて説明する。
フィールド4001は、当該統計情報についての情報を示す。“G”は、GC処理実行時に取得された統計情報であることを示す。“I”は、インポート処理実行時に取得された統計情報であることを示す。図40の例では、“G”によってGC実行時に取得された統計情報であることを示す。“#4”によってJavaVM109が起動してから通算4回目のGC処理実行時に取得された統計情報であることを示す。“(129.848)”によってJavaVM109が起動してから129.848秒後のGC処理実行時に取得された統計情報であることを示している。なお、GC処理実行時やインポート処理実行時以外のタイミングで統計情報を取得する場合は、JavaVM109が起動してから何秒後に取得した統計情報であるかを表す情報のみを出力する。
フィールド4002は、出力された統計情報の種類を示す。“[Leak]”は、リークオブジェクトに関する統計情報であることを示す。“[Leak Suspicion]”は、非アクセスオブジェクトアドレステーブル205に登録された非アクセスオブジェクトについての統計情報であることを示す。
フィールド4003は、統計情報が示されたオブジェクトを識別する情報を示す。具体的には、クラス名である。図40の例では、クラス名“java.user.ClassA”のリークオブジェクトがあることを表している。
フィールド4004は、フィールド4003で示されたクラス名のオブジェクトの合計サイズと、当該オブジェクトが配置された領域のサイズを順に示すフィールドである。図40の例では、クラス名“java.user.ClassA”のリークオブジェクトの合計サイズが99758KBであって、サイズが1048576KBの外部ヒープ領域110に格納されていることを示している。
利用者は、オブジェクト統計情報を参照することによって、クラスごとにメモリリークが発生したオブジェクトを把握して、メモリリークの原因追求などに役立てることができる。また、図41に示すオブジェクト詳細情報を参照することによって、さらに詳細にメモリの使用状況などを解析することができる。
図41は、本発明の実施の形態のJavaVM109によって出力装置130に出力されるオブジェクト詳細情報の一例を示す図である。以下、出力されたオブジェクト詳細情報の各フィールドについて説明する。
フィールド4101及び4102は、図40に示されたオブジェクト統計情報におけるフィールド4001及び4002と同じ内容である。
フィールド4103は、オブジェクト詳細情報が出力されるオブジェクトのクラス名を示す。フィールド4104は、オブジェクト詳細情報が出力されるオブジェクトの配置アドレスを示す。図41の例では、アドレス“0x72ff3448”に配置されたクラス名“java.user.ClassA”のオブジェクトが、リークオブジェクトであることを示している。
フィールド4105は、フィールド4104に示されたオブジェクトを参照しているオブジェクトのクラス名を示す。フィールド4106は、フィールド4104に示されたオブジェクトを参照しているオブジェクトの配置アドレスを示す。フィールド4107は、フィールド4104に示されたオブジェクトを参照するために使用されるオブジェクト参照フィールドのアドレスを示す。図41の例では、アドレス“0x72ff3448”に配置されたリークオブジェクトを、アドレス“0x5ae2f208”に配置されたクラス名“java.user.ReferenceClassA”のオブジェクトがアドレス“0x5ae2f210”のオブジェクト参照フィールドを使用して参照していることを表している。
図42は、本発明の実施の形態のJavaVM109によって出力装置130に出力されるGC処理の実行情報を表示する画面の一例を示す図である。
図42の画面表示例には、領域4201、領域4202、領域4203及び領域4204が含まれている。領域4201の縦軸は、外部ヒープ領域110の使用量4205を示す。領域4202の縦軸は、Javaヒープ領域122の使用量4206を示す。領域4203の縦軸は、GC処理の実行時間4207を示す。領域4204は、領域4201から4203に表示された情報の詳細を表示する領域である。
領域4201、領域4202、及び領域4203の横軸は、JavaVM109が起動されてからの経過時間を示し、すべての領域で同一の時間軸を示している。このように共通の時間軸でGC処理の実行情報を表示することによって、GC処理による外部ヒープ領域110の使用量4205の変化、Javaヒープ領域122の使用量4206の変化、及びGC処理に要した時間などを容易に把握することができる。
また、領域4201、領域4202、又は領域4203の位置を入力装置132から指定することによって、当該指定位置の時刻、当該時刻に対する使用量4205、使用量4206、又は実行時間4207の詳細を領域4204に表示することも可能である。
図43は、本発明の実施の形態のJavaVM109によって出力装置130に出力されるGC処理による領域使用量の変化を示す画面の一例を示す図である。
図43は、図42の領域4201又は領域4202、あるいは領域4201及び領域4202を併せた領域を示している。また、図43に示したように、本発明の実施の形態によるGC処理を実行する場合の使用量と、実行しない場合の使用量とを示してもよい。
図43には、本発明の実施の形態のGC処理を実行することによって、リークオブジェクト112を外部ヒープ領域110に再配置する場合のJavaヒープ領域122の使用量4206、リークオブジェクト112を外部ヒープ領域110に再配置しない場合のJavaヒープ領域122の使用量4305、及び、GC処理を実行しない場合のJavaヒープ領域122の使用量4303が示されている。また、Javaヒープ領域122のサイズ4301を重ねて表示することによって、Javaヒープ領域122の残量を把握することも可能である。
利用者は、図43に示した画面を参照することによって、Javaヒープ領域122のメモリ不足エラーの発生地点を予測又は確認することができる。具体的には、GC処理を全く実行しない場合には、サイズ4301と使用量4303の交点4302でメモリ不足エラーが発生することを把握できる。また、リークオブジェクト112を外部ヒープ領域110に再配置しない場合には、サイズ4301と使用量4305の交点4304でメモリ不足エラーが発生することを把握できる。
本発明の実施の形態によれば、検出されたリークオブジェクトを外部ヒープ領域に再配置することによって、Javaヒープ領域の空き領域を拡大することができる。
また、本発明の実施の形態によれば、メモリリークの可能性が高いと判定されたオブジェクトであっても、再びアクセスすることが可能であるため、高い堅牢性を実現することができる。
さらに、本発明の実施の形態によれば、GC処理の発生頻度を少なくすることができるため、GC処理の実行にともなうアプリケーションプログラム実行の処理速度の低下を抑えることができる。