(57)【特許請求の範囲】
【請求項１】
Ｊａｖａバイトコードをコンパイラを使用してコンピュータによってマシン・コードに変換して実行する方法であり、
メソッドのコンパイル処理を行うと共に、メソッドのコンパイル処理により生成されたマシン・コードのうちスタックポインタを変化させるマシン・コードのアドレスと変化後のメソッドのスタックフレームのサイズに関する情報である初期フレームサイズからの変化量との対を前記コンピュータに含まれる記憶装置に記録し、当該対から構成される変化表と初期フレームサイズとをコンパイルされたメソッドに対応して前記コンピュータに含まれる管理ブロックに登録するコンパイル方法。
【請求項２】
Ｊａｖａバイトコードをコンパイラを使用してコンピュータによってマシン・コードに変換して実行する場合であって、メソッドのコンパイル処理を行うと共に、メソッドのコンパイル処理により生成されたマシン・コードのうちスタックポインタを変化させるマシン・コードのアドレスと変化後のメソッドのスタックフレームのサイズに関する情報である初期フレームサイズからの変化量との対から構成される変化表と初期フレームサイズとが各メソッドに対応して前記コンピュータに含まれる管理ブロックに登録されている場合に、スタック・トレーサを使用してコンピュータによってスタックのベースポインタが指すべきベースアドレスのトレースを行なう方法であって、
トレースのため一時停止した時の実行コードのアドレスとスタックポインタのアドレスを取得し且つ前記コンピュータに含まれる記憶装置に格納し、
前記管理ブロックから初期フレームサイズと前記実行コードを含むメソッドの前記変化表とを取得し、前記実行コードのアドレスと前記初期フレームサイズと前記変化表とを引数としてフレームサイズ関数を呼び、前記スタックポインタのアドレスと前記フレームサイズ関数が出力する現在フレームサイズからベースポインタが指すべきベースアドレスを計算し且つ前記コンピュータに含まれる記憶装置に格納する
スタック・トレース方法。
【請求項３】
Ｊａｖａバイトコードをコンパイラを使用してコンピュータによってマシン・コードに変換して実行する場合であって、メソッドのコンパイル処理を行うと共に、メソッドのコンパイル処理により生成されたマシン・コードのうちスタックポインタを変化させるマシン・コードのアドレスと変化後のメソッドのスタックフレームのサイズに関する情報である初期フレームサイズからの変化量との対から構成される変化表と初期フレームサイズとが各メソッドに対応して前記コンピュータに含まれる管理ブロックに登録されており且つ所定のコンパイラによりコンパイルされた第１メソッドが前記所定のコンパイラによりコンパイルされていない第２メソッドを呼び出した時に生成される、前記第１メソッドのスタック・フレームを指すレコードが記憶されている場合に、スタック・トレーサを使用してコンピュータによってスタックのベースポインタが指すべきベースアドレスのトレースを行なう方法であって、
前記レコードを参照して前記第１メソッドのスタック・フレームのアドレスと前記第１メソッドのスタック・フレームに保持されている実行再開アドレスとを取得し且つ前記コンピュータに含まれる記憶装置に格納し、
前記管理ブロックから初期フレームサイズと前記第１メソッドの前記変化表とを取得し、実行再開アドレスと前記初期フレームサイズと前記変化表とを引数としてフレームサイズ関数を呼び、前記第１メソッドのスタック・フレームのアドレスと前記フレーム・サイズ関数が出力する現在フレームサイズからベースポインタが指すべきベースアドレスを計算し前記コンピュータに含まれる記憶装置に格納する
スタック・トレース方法。
【請求項４】
Ｊａｖａバイトコードをマシン・コードにコンパイラを使用して変換させるコンピュータを含む装置であり、
前記コンピュータにより、
メソッドをコンパイル処理を行うと共に、メソッドのコンパイル処理により生成されたマシン・コードのうちスタックポインタを変化させるマシン・コードのアドレスと変化後のメソッドのスタックフレームのサイズに関する情報である初期フレームサイズからの変化量との対を前記コンピュータに含まれる記憶装置に記録し、当該対から構成される変化表と初期フレームサイズとをコンパイルされたメソッドに対応して前記コンピュータに含まれる管理ブロックに登録する装置。
【請求項５】
Ｊａｖａバイトコードをコンパイラを使用してコンピュータによってマシン・コードに変換して実行する場合であって、メソッドのコンパイル処理を行うと共に、メソッドのコンパイル処理により生成されたマシン・コードのうちスタックポインタを変化させるマシン・コードのアドレスと変化後のメソッドのスタックフレームのサイズに関する情報である初期フレームサイズからの変化量との対から構成される変化表と初期フレームサイズとを各メソッドに対応して前記コンピュータに含まれる管理ブロックに登録している場合に、スタック・トレーサを使用してスタックのベースポインタが指すべきベースアドレスのトレースを行なうコンピュータを含む装置であって、
前記コンピュータにより、
トレースのため一時停止した時の実行コードのアドレスとスタックポインタのアドレスが取得され前記コンピュータに含まれる記憶装置に格納し、
前記管理ブロックから取得された初期フレームサイズと実行コードを含むメソッドの前記変化表と、前記実行コードのアドレスと前記初期フレームサイズと前記変化表とを引数として呼び出されたフレームサイズ関数から出力される現在のフレームサイズと、前記スタックポインタのアドレスとを用いて、ベースポインタが指すべきベースアドレスを計算し且つ前記コンピュータに含まれる記憶装置に格納する装置。
【請求項６】
Ｊａｖａバイトコードをコンピュータによってマシン・コードに変換させるコンパイラを記憶するコンピュータ可読な記憶媒体であり、
メソッドのコンパイル処理を行うと共に、メソッドのコンパイル処理により生成されたマシン・コードのうちスタックポインタを変化させるマシン・コードのアドレスと変化後のメソッドのスタックフレームのサイズに関する情報である初期フレームサイズからの変化量との対を前記コンピュータに含まれる記憶装置に記録する機能と、当該対から構成される変化表と初期フレームサイズとをコンパイルされたメソッドに対応して前記コンピュータに含まれる管理ブロックに登録する機能とを前記コンピュータによって実現するためのコンパイラを記憶した記憶媒体。
【請求項７】
Ｊａｖａバイトコードをコンパイラを使用してコンピュータによってマシン・コードに変換して実行する場合であって、メソッドのコンパイル処理を行うと共に、メソッドのコンパイル処理により生成されたマシン・コードのうちスタックポインタを変化させるマシン・コードのアドレスと変化後のメソッドのスタックフレームのサイズに関する情報である初期フレームサイズからの変化量との対から構成される変化表と初期フレームサイズとを各メソッドに対応して前記コンピュータに含まれる管理ブロックに登録している場合に、コンピュータによってスタックのベースポインタが指すべきベースアドレスのトレースを行なうためのスタック・トレーサを格納したコンピュータ可読な記憶媒体であって、
トレースのため一時停止した時の実行コードのアドレスとスタックポインタのアドレスを取得し且つ前記コンピュータに含まれる記憶装置に格納する機能と、
前記管理ブロックから初期フレームサイズと前記実行コードを含むメソッドの前記変化表とを取得し、前記実行コードのアドレスと前記初期フレームサイズと前記変化表とを引数としてフレームサイズ関数を呼び、前記スタックポインタのアドレスと前記フレームサイズ関数が出力する現在フレームサイズからベースポインタが指すべきベースアドレスを計算し且つ前記コンピュータに含まれる記憶装置に格納する機能と、
を前記コンピュータによって実現するためのスタック・トレーサを格納した記憶媒体。
【発明の詳細な説明】
【０００１】
【発明の属する技術分野】
本発明は、コンパイル方法及びスタック・トレース方法に関し、より詳しくはＪａｖａ（Sun Microsystems社の商標）のＪＩＴ（Just In Time）コンパイラ及びそれを使用する場合におけるスタック・トレース方法に関する。
【０００２】
【従来の技術】
現在、Ｊａｖａは、ネットワークコンピューティングの共通言語としてだけでなく、プラットフォームに依存しない、オブジェクト指向言語のスタンダードな言語として広く使用されている。Ｊａｖａで書かれたプログラムはバイトコードに変換され、バイトコードはＪａｖａ仮想マシンで実行される。そのため、一度Ｊａｖａで書かれたプログラムは、Ｊａｖａをサポートしているコンピュータならば、ＣＰＵを問わずどこでも動く（マルチプラットフォーム）という利点を持つ。
【０００３】
しかしこうした利点の反面、バイトコードの仮想マシンによる実行は、機械語のコードを直接実行するのに比べて、実行性能の点で劣る。そのため、ＪＩＴコンパイラにより、Ｊａｖａプログラムの動作中に前記バイトコードを機械語コード（以下、ＪＩＴｅｄコードと呼ぶ）に変換して、バイトコードの代わりにＪＩＴｅｄコードを実行するのが一般的である。コンパイルの最小単位は、メソッドと呼ばれるサブルーチンである。実行頻度の高いコードを機械語に変換することにより、Ｊａｖａバイトコードのマルチプラットフォーム特性を残しつつ、機械語コードの性能を引き出している。
【０００４】
メソッドのＪＩＴｅｄコードは、プログラムが動作するＣＰＵに適したコードになっているという点で、Ｃコンパイラなどが生成する最適化コードと同等である。一般に、現在普及しているＣＰＵでは、サブルーチンが呼ばれると、サブルーチンは、自分が使用するローカル変数を格納するための領域（フレームと呼ぶ）をスタック上に形成する。図１は、サブルーチンＡがサブルーチンＢを、サブルーチンＢがサブルーチンＣを呼び出したときのスタックの様子である。この図において、スタックは下から上に伸びる。各領域は、サブルーチンのそれぞれのフレームを表わす。スタックポインタＳＰは、このスタックの最上部、すなわち、フレームＣの最上部を指している。サブルーチンＣがさらにサブルーチンＤを呼べば、現在のＳＰから新たにサブルーチンＤのフレームが形成され、ＳＰは、そのフレームの最上部を指し直す。各サブルーチンから戻る際、そのフレームは除去される。例えば、サブルーチンＤからサブルーチンＣに戻る場合、戻る前にサブルーチンＤのフレームは除去され、ＳＰは、サブルーチンＣがサブルーチンＤを呼び出した時の値に戻り、再びフレームＣの最上部を指す。Ｊａｖａの場合では、スレッドと呼ばれる実行単位毎にＣＰＵ資源が割り振られ、各スレッドは固有のスタック（スレッドスタックと呼ぶ）を持つ。ＪＩＴｅｄコードは、スレッドスタック上に上述したようなフレーム（以下、ＪＩＴｅｄフレームと呼ぶ）を作る。
【０００５】
スレッドスタック中にあるのは、ＪＩＴｅｄフレームだけではない。ＪＩＴｅｄコードは、Ｊａｖａ仮想マシンが提供する様々なサービスルーチンを呼び出す。サービスルーチンによっては、さらに新たなＪａｖａ仮想マシンを起動するものもある。図２は、ＪＩＴｅｄコードとそれ以外のコードのフレームが、スレッドスタック中で混じっているところを示す。アルファベット文字が付いている部分がＪＩＴｅｄフレームである。
【０００６】
スタックトレースには、通常、ベースポインタを使用する。例えば、ｘ８６のベースポインタＥＢＰは、スタック中の現在のフレームのベースアドレスを常に保持し、スタック中のフレームの検出を容易にしている。例えば、Ｃプログラムなどのデバッグの際には、スタックトレースでメソッドの呼びかけ関係を知ることは有用である。ＥＢＰによるフレーム鎖は、このためによく使われる。
【０００７】
一般的なコンパイラ最適化技術として、特にレジスタの少ないｘ８６アーキテクチャで重要な技術として、ベースポインタの省略がある。上述したＣプログラムの例の場合、デバッグが終わり、最終コードをビルドする際には、ＥＢＰをフレーム鎖から解放する最適化を行なうことによって、フレーム鎖の維持オーバヘッドが減少し、ＥＢＰレジスタを汎用レジスタとして割り当てられるようになる。これにより、高速なコードを生成することができる。この最適化は、Ｃのような言語では、実行時にスタックトレースが必要ないからこそ可能である。
【０００８】
【発明が解決しようとする課題】
ＪａｖａのＪＩＴコンパイラでは、このようなベースポインタの省略が困難である。Ｊａｖａの言語仕様で、Java.lang.SecurityManager のclassLoaderDepth()や、Java.lang.ThreadのcountStackFrames()などが、スタックトレース同等の機能を要求しているからである。他にも、例外発生時にその時のスタックトレースを例外オブジェクトに記憶する必要がある。ベースポインタを省略すると、これらが機能しない。
【０００９】
それとは別に、ＪＩＴｅｄコード破棄メカニズムにおいてもベースポインタの省略を困難にする原因がある。ＪＩＴｅｄコードを含むＪＩＴコンパイラが使用するメモリに制限がある、あるいは制限を設けるとき、クラスアンロードだけでは十分でない場合がある。例えば、ハードディスクによる仮想記憶を持たない、ネットワークコンピューティング（Network Computing ）マシン（以下、ＮＣマシン）のような、シンクライアント（ｔｈｉｎ  ｃｌｉｅｎｔ）上で動作するデスクトップ環境では、メール、ワープロ、スケジューラ等、複数のＪａｖａアプリケーションが同時に起動され、数千種類のメソッドが呼ばれうるが、かなりの割合のメソッドが各スレッドスタック中に存在しない（アクティブでない）。クラスアンロードは、Ｊａｖａシステム内に完全に使用される可能性のないクラスおよびそのメソッドしか破棄しないため、そうしたアクティブでないメソッドのＪＩＴｅｄコードを破棄しない。そこで、ＪＩＴコンパイラは、アクティブメソッドをすべてのスレッドスタック中から見つけ出し、非アクティブメソッド（の一部）を破棄してメモリをフリーにするＪＩＴｅｄコード破棄メカニズムを持っている。アクティブメソッドを正確且つ高速に発見するために、ＪＩＴｅｄコードのフレームだけを連結するフレーム鎖が欠かせない。
【００１０】
本発明の目的は、ベースポインタが省略された状況においてもスタック・トレースを行なうことができるようにすることである。
【００１１】
本発明においてコンパイル時には、メソッドのコンパイル処理と共にスタックポインタを変化させるコードのアドレスと変化後のスタックフレームのサイズに関する情報との対を記憶装置に記録し、当該対から構成される変化表と初期フレームサイズとをコンパイルされたメソッドに対応して登録する処理を行なう。変化後のスタックフレームのサイズに関する情報は、好適には、初期フレームサイズからのスタックポインタの変化量であるが、変化後のスタックフレームのサイズそのものでもよい。前者の場合には変化表は初期フレームサイズを含むか、別途初期フレームサイズを用意する。
【００１２】
このようなコンパイル時の処理が行なわれており且つ好適な実施形態におけるＪＩＴｅｄコード実行時に一時停止しトレースを行なう場合には、トレースのため一時停止した時の実行コードのアドレスとスタックポインタのアドレスを取得し且つ記憶装置に格納し、実行コードのアドレスとスタックポインタのアドレスと当該実行コードを含むメソッドの変化表とを用いて、ベースポインタが指すべきベースアドレスを計算し且つ記憶装置に格納する。
【００１３】
一方、好適な実施形態におけるＪＩＴｅｄラストフレーム・レコード方式（所定のコンパイラによりコンパイルされた第１メソッドが所定のコンパイラによりコンパイルされていない第２メソッドを呼び出した時に、第１メソッドのスタック・フレームを指すレコードが生成される方式）を採用しており且つ好適な実施形態における非ＪＩＴｅｄコード実行時に一時停止しトレースを行なう場合には、前記レコードを参照して第１メソッドのスタック・フレームのアドレスと第１メソッドのスタック・フレームに保持されている実行再開アドレスとを取得し且つ記憶装置に格納し、第１メソッドのスタック・フレームのアドレスと実行再開アドレスと第１メソッドの変化表とを用いて、ベースポインタが指すべきベースアドレスを計算し記憶装置に格納する。
【００１４】
このようにすると、ベースポインタを省略する最適化を行なっても、スタック・トレースを行なうことができる。従って、上述のようなＪａｖａ言語仕様に関する問題は解決し、ベースポインタの省略最適化を行なうことにより、Ｊａｖａのコンパイルコードの品質を大きく向上させることができる。一方、ＪＩＴｅｄコード破棄メカニズムを採用している環境では、品質を落さずに効率的なアクティブメソッド検索手法を実現することができる。
【００１５】
以上本発明の処理の流れを説明したが、本発明はこれらの処理を実施する装置や、コンピュータにこれらの処理を実施させるプログラムの形態によっても実現可能である。このプログラムを、フロッピー・ディスクやＣＤ−ＲＯＭ等の記憶媒体又は他の形態の記憶装置に格納することは、通常当業者が行う事項である。
【００１６】
【発明の実施の形態】
本発明の装置構成を図５を用いて説明する。サーバ・コンピュータ１及びクライアント・コンピュータ５はネットワーク３を介して接続されている。クライアント・コンピュータ５は、ＪａｖａＶＭ（Virtual Machine ）５２及びＯＳ（Operating System）５３及びハードウエア（ＣＰＵ及びメモリを含む）５５を含む。さらに、ＪａｖａＶＭ５２は、Ｊａｖａインタープリタ５４又はＪａｖａ  ＪＩＴコンパイラ５６、及びスタックのトレースを行うトレーサ６０を含む。インタープリタ５４及びＪＩＴコンパイラ５６の両者を有している場合もある。なお、クライアント・コンピュータ５は、通常のコンピュータの他、メモリの大きさが小さかったり、ハードディスク等の補助記憶装置を含まないような、いわゆるネットワーク・コンピュータや情報家電の場合もある。
【００１７】
サーバ・コンピュータ１では、Ｊａｖａソースコード１０は、Ｊａｖａコンパイラ１２によりコンパイルされる。このコンパイルの結果が、バイトコード１４である。このバイトコード１４は、ネットワーク３を介してクライアント・コンピュータ５に送信される。バイトコード１４は、クライアント・コンピュータ５内のＷＷＷブラウザ（World Wide Web Browser）などに設けられたＪａｖａ仮想マシン（Java VM ）５２にとってネイティブ・コードであり、実際ハードウエア５５のＣＰＵにて実行する場合には、Ｊａｖａインタープリタ５４や、ＪａｖａＪＩＴコンパイラ５６を用いる。インタープリタ５４は、実行時にバイトコード１４をデコードし、命令ごとに用意される処理ルーチンを呼び出して実行する。一方、ＪＩＴコンパイラ５６は、バイトコードを事前にあるいは実行する直前にコンパイラを用いてマシン・コード５８（機械語コードとも言う）に変換してそれをＣＰＵで実行する。
【００１８】
以下、本発明に関連するＪＩＴコンパイラ５６及びトレーサ６０と、これらに関連する機能について説明する。
【００１９】
図３はクライアント・コンピュータ５のメインメモリ上に展開された、本発明に関係する機能のブロック図である。ＪＩＴコンパイラ５６は、バイトコード１４からマシン・コード５８を生成するものである。あるメソッドのマシン・コードは図３においてメソッド４０として示されている。ＪＩＴコンパイラ５６はこのメソッドのコンパイル時に、ＪＩＴｅｄ管理ブロック１００を生成する。また、ＪＩＴコンパイラ５６は、本発明に関係するＳＰ変化表１０２と初期フレームサイズ１０３をＪＩＴｅｄ管理ブロック１００に登録する。ＪＩＴｅｄ管理ブロック１００は、ＪＩＴコンパイラ５６にコンパイルされたメソッドの管理ブロックである。さらに、ＪＩＴコンパイラ５６は、マシン・コード５８のアドレスからメソッドを特定するためのＪＩＴｅｄコード・データベース（ＤＢ）８０に、生成したメソッド４０の登録を行う。メソッド４０は実際に実行されるとラストフレーム・レコード７０を生成する。トレーサ６０は、このラストフレーム・レコード７０と、ＪＩＴｅｄコードＤＢ８０と、ＪＩＴｅｄコードＤＢ８０から特定されるＳＰ変化表１０２及び初期フレームサイズ１０３と、現在のフレームサイズを出力するフレームサイズ関数９０と、ＳＰや現在実行アドレスを含むコンテキスト（図示せず）とを用いて、スタックをトレースする。
【００２０】
では、図３の各構成要素の動作をより詳細に図６及び図７を用いて説明する。
【００２１】
図６はＪＩＴコンパイラ５６がコンパイル時に行う動作である。ＪＩＴコンパイラ５６は、メソッドのコンパイル処理を行う（ステップ６１０）。このコンパイル処理には、マシン・コード５８（図３ではメソッド４０）の生成の他に、ＳＰ変化表１０２及びＪＩＴｅｄ管理ブロック１００の作成も含む。当然、作成されたマシン・コード及び情報はメインメモリに格納される。コンパイル処理が終了すると、そのメソッドのスタック・フレームの初期フレームサイズ１０３と最終的なＳＰ変化表１０２をＪＩＴｅｄ管理ブロック１００に登録する（ステップ６２０）。ＳＰ変化表１０２とは、ＳＰの値を変化させるマシン・コードのアドレス（そのマシン・コード内のオフセットでよい）と、初期フレームサイズからの変化量という対を、アドレス順に記憶したものである。通常、ＳＰのアドレスが最初に作成したフレームの先頭アドレスより増えるのは、メソッドとライブラリルーチンの両者（以下、関数と呼ぶ）の呼び出し時が主である。この関数呼び出しの引数をスタックに積む、引数のスタック領域を確保する、あるいは削除するマシン・コードをコンパイラが生成する毎に、ＳＰの値を変化させるマシン・コードのアドレスとＳＰの初期フレームサイズからの変化量を記録していけば、ＳＰ変化表１０２は作成できる。但し、マシン・コード生成後に、基本ブロックの入れ替えなどを実施する場合もあるので、アドレスをキーとしてソートする。基本ブロックの入れ替えなどを行わなければ、自然にソートされている。ＳＰ変化表１０２はメソッドごとに作成する。なお、ＳＰの値を変化させるコードはそれほど多くないため、ＳＰ変化表１０２のサイズは小さくて済む。
【００２２】
次にトレーサ６０等がトレース時に行う動作を説明する。但し、以下の説明では、特願平１０−２６７８４２号で開示したＪＩＴｅｄラストフレーム方式が使用されることを前提としているので、この方式について少し説明しておく。図４は、ある時点でのスレッドスタックの一般的な状態を示す線図である。Ａ，Ｂ，Ｃ及びＤがメソッドのＪＩＴｅｄフレームである。ＡとＢ、ＣとＤは連続している（ＪＩＴｅｄフレーム列と呼ぶ）。図４において、ＪＩＴｅｄフレーム列の先頭を指している□はＪＩＴｅｄラストフレーム・レコードである。このＪＩＴｅｄラストフレーム・レコードは、連続するＪＩＴｅｄフレームを管理し、それ自身ＬＩＦＯ（Last In First Out ）のリストを構成する。ＪＩＴｅｄラストフレーム・レコードは、ＪＩＴｅｄコードがサービス・ルーチン等の非ＪＩＴｅｄコードを呼ぶ毎に作成され、リストを更新する。すなわち、ＪＩＴｅｄコードにはサービス・ルーチン等を呼ぶ直前にＪＩＴｅｄラストフレーム・レコードを生成するマシン・コードが含まれている。ＪＩＴｅｄラストフレーム・レコードが指すＪＩＴｅｄフレーム列の先頭のＪＩＴｅｄフレームは、そのフレームで実行するメソッドから非ＪＩＴｅｄコードへの脱出が起こっていることを示している。なお、非ＪＩＴｅｄコードからＪＩＴｅｄコードを呼ぶ場合には、非ＪＩＴｅｄフレームの次にＪＩＴｅｄフレームが生成されるが、この切り換えも別途記録されているものとする。
【００２３】
では図７にトレーサ６０等がトレース時に行う動作を示す。なお、トレーサ６０が動作するときには、スレッドは停止させられている。まず、トレーサ６０はＪＩＴｅｄコード内で停止しているか判断する（ステップ７１０）。ＪＩＴｅｄコードか否かという判断は、コンテキストから判断できる。もし、ＪＩＴｅｄコード内で停止していれば（例えば図１の状態）、トレーサ６０はコンテキストから停止アドレスａｄｄｒとＳＰを取得する（ステップ７２０）。一方、ＪＩＴｅｄコード内で停止しているわけではなく、非ＪＩＴｅｄコード内で停止している場合には（例えば図２の状態）、トレーサ６０は、ＪＩＴｅｄラストフレーム・レコード（のリスト）７０の最も上の（最も新しい）情報を参照して、そのＪＩＴｅｄラストフレーム・レコードが指すアドレスと、それが指すアドレスのフレームでの実行再開アドレスとを取得し、それぞれＳＰとａｄｄｒとする（ステップ７３０）。実行再開アドレスは、フレームに記憶されている。
【００２４】
次に、トレーサ６０は取得したａｄｄｒでＪＩＴｅｄコードＤＢ８０を引いてメソッドを特定する。そして、そのメソッドのＪＩＴｅｄ管理ブロック１００から初期フレームサイズ１０３とＳＰ変化表１０２（のアドレス）を取得する（ステップ７４０）。そして、トレーサ６０は、ａｄｄｒ、初期フレームサイズ１０３及びＳＰ変化表１０２（のアドレス）を引数としてフレームサイズ関数９０を呼ぶ。フレームサイズ関数９０は、ＳＰ変化表１０２においてａｄｄｒをキーとしてバイナリサーチを行い、そのａｄｄｒに対応する変化量を取得し、初期フレームサイズを用いて現在フレームサイズを計算する。そしてフレームサイズ関数９０は現在フレームサイズをトレーサ６０に返す（ステップ７５０）。トレーサ６０は、ＳＰと現在フレームサイズから、現在のフレームのベースアドレス、すなわちベースポインタが指すべきアドレスを計算する（ステップ７６０）。このアドレスにフレームの切れ目がある。
【００２５】
次にトレーサ６０は、この現在フレームがＪＩＴｅｄフレーム列の最後のフレームであるか判断する（ステップ７７０）。これは、非ＪＩＴｅｄコードがＪＩＴｅｄコードを呼び出す場合には、それらのフレームの切れ目のアドレスは記録されているので、このアドレスと計算されたベースポインタのアドレスを比較すればよい。もし、現在フレームがＪＩＴｅｄフレーム列の最後のフレームでなければ、トレーサ６０は、次の（下の）フレームでの実行再開アドレスを取得し、ベースポインタのアドレスをＳＰとし、実行再開アドレスをａｄｄｒとしてステップ７４０に戻る（ステップ７８０）。
【００２６】
もし、この現在フレームがＪＩＴｅｄフレーム列の最後のフレームであると判断された場合には、トレーサ６０は、次のＪＩＴｅｄフレーム列が存在するか否かで判断する（ステップ７９０）。これはＪＩＴｅｄラストフレーム・レコード（のリスト）７０の次のレコードが存在するかで判断できる。もし、次のＪＩＴｅｄラストフレーム・レコードが存在しない場合には、処理を終了する（ステップ８００）。一方、次のＪＩＴｅｄラストフレーム・レコードが存在する場合には、次のＪＩＴｅｄラストフレーム・レコードについてステップ７３０を実行する。そして、トレーサ６０はステップ７４０以降の処理を実施する。
【００２７】
以上の説明ではＳＰの初期フレームサイズからの変化量と初期フレームサイズの対を記録する例を示したが、場合によっては変化後のＳＰが指しているスタックフレームのサイズ自身を記録するようにしてもよい。この際には、初期フレームサイズを記録する必要はない。
【００２８】
なお、図６及び図７の処理の途中で取得される又は計算されるアドレスは記憶装置（例えばメインメモリ）に記憶される。
【００２９】
【発明の効果】
本発明によれば、ベースポインタを省略する最適化を行っても、フレームトレースを行なうことができる。従って、Ｊａｖａの言語仕様を変更することなく、Ｊａｖａのコンパイルコードの品質を大きく向上させることができる。一方、ＪＩＴｅｄコード破棄メカニズムが使用される環境では、効率的なアクティブメソッド検索が可能になる。
【図面の簡単な説明】
【図１】  サブルーチンＡがサブルーチンＢを、サブルーチンＢがサブルーチンＣを呼び出したときのスタックを示す線図である。
【図２】  ＪＩＴｅｄコードとそれ以外のコードのフレームが混在するスレッドスタックを示す線図である。
【図３】  本発明によるスタックトレース方法の動作を説明する線図である。
【図４】  ある時点でのスレッドスタックの一般的な状態を示す線図である。
【図５】  本発明における装置構成の一例を示す図である。
【図６】  図３および図５に示すＪＩＴコンパイラがコンパイル時に行う動作を説明するフローチャートである。
【図７】  図３および図５に示すトレーサがトレース時に行う動作を説明するフローチャートである。
【符号の説明】
１  サーバ・コンピュータ
３  ネットワーク
５  クライアント・コンピュータ
１０  Ｊａｖａソースコード
１２  Ｊａｖａコンパイラ
１４  バイトコード
５２  ＪａｖａＶＭ
５４  Ｊａｖａインタプリタ
５６  Ｊａｖａ  ＪＩＴコンパイラ
５８  マシンコード
６０  ガベージ・コレクタ
５３  ＯＳ
５５  ハードウエア（ＣＰＵ及びメモリを含む）
【図１】
0004088379.tif 000002
【図２】
0004088379.tif 000003
【図３】
0004088379.tif 000004
【図４】
0004088379.tif 000005
【図５】
0004088379.tif 000006
【図６】
0004088379.tif 000007
【図７】
0004088379.tif 000008