(57)【特許請求の範囲】
【請求項１】
コンピュータの処理によって、第１のプログラミング言語の処理系によって生成された実行形式のバイトコードを、第２のプログラミング言語のソース・コードに対応させるためるようにコードを変換するコード変換プログラムであって、
前記コンピュータに、
前記第１のプログラミング言語の処理系によって生成された実行形式のバイトコードを順次読取るステップと、
前記第２のプログラミング言語の言語要素に直接対応していない、スタック操作関連の命令を行うコードが見出されたことに応答して、前記見出された命令の代わりに、一時変数への代入式、引数の一部をそのままかえすだけのダミーのメソッドの呼び出し、前記一時変数の読み出し式のいずれかの組み合わせを挿入するステップと、
前記第２のプログラミング言語の言語要素が直接対応していない、スタックに値を残して戻り値をもたないメソッドを呼び出すコードが見出されたことに応答して、追加の第１の引数と元の引数をもち、元のメソッド・コールを実行し、該追加の第１の引数をそのまま返す新規メソッドを生成し、戻り値をもたないメソッドを呼び出しの代わりに、前記新規メソッドの呼び出しを挿入するステップ
を実行させる、
コード変換プログラム。
【請求項２】
請求項１に記載された前記コード変換プログラムの機能を、前処理として備えることにより、余分な一時変数を導入しない逆コンパイラ・プログラム。
【請求項３】
請求項１に記載された前記コード変換プログラムの機能を、後処理として備えることにより、一時変数を導入しない逆コンパイラによって容易に逆コンパイル可能なようなバイトコードを生成する前記第１のプログラミング言語の処理系プログラム。
【請求項４】
前記第１のプログラミング言語がPHP言語であり、前記第２のプログラミング言語がJavaである、請求項１に記載のコード変換プログラム。
【請求項５】
コンピュータの処理によって、第１のプログラミング言語の処理系によって生成された実行形式のバイトコードを、第２のプログラミング言語のソース・コードに対応させるためるようにコードを変換するコード変換方法であって、
前記コンピュータの処理により、前記第１のプログラミング言語の処理系によって生成された実行形式のバイトコードを順次読取るステップと、
前記コンピュータの処理により、前記第２のプログラミング言語の言語要素に直接対応していない、スタック操作関連の命令を行うコードが見出されたことに応答して、前記見出された命令の代わりに、一時変数への代入式、引数の一部をそのままかえすだけのダミーのメソッドの呼び出し、前記一時変数の読み出し式のいずれかの組み合わせを挿入するステップと、
前記コンピュータの処理により、前記第２のプログラミング言語の言語要素が直接対応していない、スタックに値を残して戻り値をもたないメソッドを呼び出すコードが見出されたことに応答して、追加の第１の引数と元の引数をもち、元のメソッド・コールを実行し、該追加の第１の引数をそのまま返す新規メソッドを生成し、戻り値をもたないメソッドを呼び出しの代わりに、前記新規メソッドの呼び出しを挿入するステップを有する、
コード変換方法。
【請求項６】
前記第１のプログラミング言語がPHP言語であり、前記第２のプログラミング言語がJavaである、請求項５に記載のコード変換方法。
【請求項７】
コンピュータの処理によって、第１のプログラミング言語の処理系によって生成された実行形式のバイトコードを、第２のプログラミング言語のソース・コードに対応させるためるようにコードを変換するコード変換システムであって、
前記第１のプログラミング言語の処理系によって生成された実行形式のバイトコードを順次読取る手段と、
前記第２のプログラミング言語の言語要素に直接対応していない、スタック操作関連の命令を行うコードが見出されたことに応答して、前記見出された命令の代わりに、一時変数への代入式、引数の一部をそのままかえすだけのダミーのメソッドの呼び出し、前記一時変数の読み出し式のいずれかの組み合わせを挿入する手段と、
前記コンピュータの処理により、前記第２のプログラミング言語の言語要素が直接対応していない、スタックに値を残して戻り値をもたないメソッドを呼び出すコードが見出されたことに応答して、追加の第１の引数と元の引数をもち、元のメソッド・コールを実行し、該追加の第１の引数をそのまま返す新規メソッドを生成し、戻り値をもたないメソッドを呼び出しの代わりに、前記新規メソッドの呼び出しを挿入する手段を有する、
コード変換システム。
【請求項８】
前記第１のプログラミング言語がPHP言語であり、前記第２のプログラミング言語がJavaである、請求項７に記載のコード変換システム。
【発明の詳細な説明】
【技術分野】
【０００１】
この発明は、コンピュータによる処理のためにコードを変換する技術に関し、より詳しくは、Java(R)バイトコードのような、仮想マシン上で実行されるコードを変換するための、コード変換プログラム、方法及びシステムに関するものである。
【背景技術】
【０００２】
従来より、サーバ環境で使用されるプログラミング言語処理系、あるいは実行系として、PHPのような動的スクリプト言語と、Java(R)のようなより静的なプログラミング言語が使用されているが、近年になって、Java(R)のクラス資産をPHPなどから簡易に呼び出せるように、Java(R)仮想マシンあるいは、コンピュータ共通言語基盤（ＣＬＩ）のような静的な言語プラットフォーム上でPHPのような動的スクリプト言語が、静的な言語プラットフォームのクラスを宣言し、タイプ付けされていないアクセスを可能ならしめる仕組みが提供されるようになってきている。
【０００３】
特に、Java(R)仮想マシン上で動作するPHPとしてのP8、RubyとしてのJRuby、PythonとしてのJythonなどが知られている。これらのJava(R)仮想マシン上で動く動的スクリプト言語は、当然に、Java(R)バイトコードを生成するが、パフォーマンス・チューニングなどの目的で、Java(R)のエキスパートが、それらの生成されたJava(R)バイトコードを、Java(R)のソースコードに逆コンパイルすることを要望する場合がある。
【０００４】
JDKに標準で付属しているjavapでは、Java(R)バイトコードを逆アセンブルするのみであるが、Java(R)バイトコードを、Java(R)のソースコードに逆コンパイルするツールとして、SourceAgain, JAD, JODEなどのツールが知られている。
【０００５】
もともとJava(R)で書かれたソースコードからjavacなどで生成されたJava(R)バイトコードであるなら、よほど難読化処理がなされていない限り、上述の逆コンパイル・ツールでJava(R)のソースコードに逆コンパイルすることは困難ではない。
【０００６】
しかし、P8、JRuby、Jythonなどの動的スクリブティング言語処理系だと、本質的に静的言語処理系であるJava(R)とは、言語仕様が異なるため、生成されたJava(R)バイトコードに、例えばswapのような、もともとのJava(R)にないバイトコード演算子が含まれることがある。
【０００７】
従って、動的スクリブティング言語処理系によって生成されたJava(R)バイトコードを、そのまま普通の逆コンパイル・ツールで逆コンパイルしようとしてもうまくいかず、Java(R)のソースコードが得られない、という問題がある。
【０００８】
Jerome Miecznikowski and Laurie Hendren, "Decompiling Java Bytecode: Problems, Traps and Pitfalls",in Procs. of CC 2002, LNCS 2304, Springer-Verlag, 2002, pp.111-127は、必ずしも純正のJava(R)コンパイラで生成されたのではないJava(R)バイトコードに対して、適宜コード変換を施すことにより、強制的に逆コンパイルを可能ならしめる技術を開示する。
【０００９】
上記非特許文献による強制逆コンパイル技術は、様々な処理系により生成されたJava(R)バイトコードを逆コンパイルすることを可能ならしめるが、コード変換の過程で、沢山の一時ローカル変数を挿入するので、Java(R)ソースコードに逆コンパイルした際に、これら多数の一時ローカル変数の存在が、ソースコードの可読性を低下させてしまう、という問題がある。
【００１０】
例えば、下記のようなバイトコードの列（<exprX>はJava(R)の式に相当する部分バイトコード列を意味している）を想定する。
<expr0>
<expr1>
<expr2>
<expr3>
swap
invokestatic C.foo3(P,P)
invokevirtual P.foo2(P)
invokevirtual P.foo1(P)
areturn
これは、上記非特許文献による強制逆コンパイル技術を経た後では、逆コンパイルしたソースコード（<exprX>はJava(R)の式を意味している）は、下記のようになる。
【００１１】
C tmp0 = <expr0>;
P tmp1 = <expr1>;
P tmp2 = <expr2>;
return tmp0.foo1(tmp1.foo2(C.foo3(<expr3>,tmp2)));
【００１２】
このように多数の一時変数が残ってしまう。
【先行技術文献】
【非特許文献】
【００１３】
【非特許文献１】Jerome Miecznikowski and Laurie Hendren, "Decompiling Java Bytecode: Problems, Traps and Pitfalls",in Procs. of CC 2002, LNCS 2304, Springer-Verlag, 2002, pp.111-127
【発明の概要】
【発明が解決しようとする課題】
【００１４】
従って、この発明の目的は、Java(R)仮想マシン上で動作する動的スクリプト言語処理系などの非Java(R)ネイティブな処理系によって生成されたJava(R)バイトコードを逆コンパイルして得られるJava(R)ソースコードの可読性を高めることにある。
【課題を解決するための手段】
【００１５】
この発明によれば、Java(R)逆コンパイラにかける前に、コード変換器によって、Java(R)バイトコードに対して、次のような変換が施される。
【００１６】
すなわち、コード変換器は、Java(R)バイトコードにおいて、
Java(R)の言語要素に直接対応していない、スタック操作関連の命令を行うコードまたは、
Java(R)の言語要素が直接対応していない、スタックに値を残して戻り値をもたないメソッドを呼び出すコード、
を見出す。
【００１７】
そして、コード変換器は、Java(R)の言語要素に直接対応していない、スタック操作関連の命令を行うコードを見出した場合は、見出された命令の代わりに、一時変数への代入式、引数の一部をそのままかえすだけのダミーのメソッドの呼び出し、前記一時変数の読み出し式のいずれかの組み合わせを挿入し、
Java(R)の言語要素が直接対応していない、スタックに値を残して戻り値をもたないメソッドを呼び出すコードを見出した場合は、追加の第１の引数と元の引数をもち、元のメソッド・コールを実行し、該追加の第１の引数をそのまま返す新規メソッドを作り、戻り値をもたないメソッドを呼び出しの代わりに、前記新規メソッドの呼び出しを挿入する処理を行う。
【００１８】
このようなバイトコードの変換を行うことにより、従来技術ではソースコードへの逆コンパイル時にもたらされていた多数の一時変数が削減されて、ソースコードの可読性が高められる。すなわち、上記と同じバイトコードに対して、ソースコードは、次のようになる。
P tmp;
return <expr0>.foo1(<expr1>.foo2(C.foo3(DBF.swap(tmp=<expr2>,<expr3>),tmp)));
【００１９】
このようなコード変換器は、通常のJava(R)バイトコードの逆コンバイラに前段に配置してもよいし、Java(R)バイトコードの逆コンバイラの一部の処理ロジックとして組み込んでもよい。
【００２０】
なお、この発明は、Java(R)のバイトコードの逆コンパイルのみならず、スタック操作関連の命令をもつ、実行系のための中間コードを生成する任意の言語処理系により生成されるバイトコードを、通常の逆コンパイラでソースコードに戻せるようにする目的で、コード生成処理の一部としてのコード変換処理に適用可能である。
【発明の効果】
【００２１】
この発明によれば、ターゲットの言語処理系が直接対応していない命令に対して、所定のメソッドの呼び出しのコードを挿入することにより、逆コンパイル時のソースコードの可読性を高めることができるという効果が得られる。
【図面の簡単な説明】
【００２２】
【図１】ハードウェアの概要ブロック図である。
【図２】ソフトウェアの階層を示す図である。
【図３】機能論理ブロック図である。
【図４】コード変換器の処理のフローチャートを示す図である。
【発明を実施するための形態】
【００２３】
以下、図面に従って、本発明の実施例を説明する。これらの実施例は、本発明の好適な態様を説明するためのものであり、発明の範囲をここで示すものに限定する意図はないことを理解されたい。また、以下の図を通して、特に断わらない限り、同一符号は、同一の対象を指すものとする。
【００２４】
図１を参照すると、本発明の一実施例に係るシステム構成及び処理を実現するためのコンピュータ・ハードウェアのブロック図が示されている。図１において、システム・バス１０２には、ＣＰＵ１０４と、主記憶（ＲＡＭ）１０６と、ハードディスク・ドライブ（ＨＤＤ）１０８と、キーボード１１０と、マウス１１２と、ディスプレイ１１４が接続されている。ＣＰＵ１０４は、好適には、３２ビットまたは６４ビットのアーキテクチャに基づくものであり、例えば、インテル社のPentium（商標）４、インテル社のCore(商標) 2 DUO、AMD社のAthlon（商標）などを使用することができる。主記憶１０６は、好適には、１ＧＢ以上の容量、より好ましくは、２ＧＢ以上の容量をもつものである。
【００２５】
ハードディスク・ドライブ１０８には、オペレーティング・システム２０２（図２で後述）が、格納されている。オペレーティング・システム２０２は、Linux（商標）、マイクロソフト社のWindows(商標) 7、Windows XP（商標）、Windows(商標)2003サーバ、アップルコンピュータのMac OS（商標）などの、ＣＰＵ１０４に適合する任意のものでよい。オペレーティング・システム２０２は、システムの起動時に、主記憶１０６にロードされて動作する。
【００２６】
ハードディスク・ドライブ１０８にはさらに、Java(R)仮想マシン（ＶＭ）２０４（図２で後述）を実現するためのJava(R) Runtime Environmentプログラムが保存され、システムの起動時に、主記憶１０６にロードされて動作する。
【００２７】
ハードディスク・ドライブ１０８にはさらに、典型的にはP8である、PHP用Java(R)バイトコード生成器２０６（図２で後述）、及び、PHPで書かれたソースコード２０８（図２で後述）、本発明の特徴機能を実装したコード変換器３０６（図３で後述）、及び逆コンパイラ３０８（図３で後述）が保存されている。コード変換器３０６及び逆コンパイラ３０８は、Ｃ、Ｃ＋＋などの任意のコンピュータ言語で書かれていてよいが、好適には、Java(R)で書かれて、Java(R)仮想マシン２０４上で動作する。
【００２８】
図２は、ソフトウェアの階層を示す図である。下層のオペレーティング・システム２０２上では、Java(R)仮想マシン２０４が動作する。Java(R)仮想マシン２０４上では、PHP用Java(R)バイトコード生成器２０６が動作する。PHP用Java(R)バイトコード生成器２０６は、PHPソースコード２０８を、Java(R)仮想マシン２０４が解釈可能な、Java(R)バイトコードに変換する。PHPソースコード２０８とは、拡張子がphpで、<?php ・・・  ?>で指定された箇所に、PHPの言語仕様で規定されたステートメントが書かれたファイルである。
【００２９】
図３は、機能論理ブロック図である。図３において、PHP用Java(R)バイトコード生成器２０６は、上述のように、PHPソースコード２０８を、Java(R)バイトコード３０４に変換する。変換されたJava(R)バイトコード３０４は、主記憶１０６にロードしてもよいし、ハードディスク・ドライブ１０８にセーブしてもよい。
【００３０】
コード変換器３０６は、本発明の機能を実施するために、逆コンパイラ３０８に引き渡す前に、Java(R)バイトコード３０４を変換する機能をもつ。コード変換器３０６の機能は、図４のフローチャートを参照して、後で詳細に説明する。逆コンパイラ３０８は、SourceAgain, JAD, JODEなどの既知の任意のものでよい。但し、コード変換器３０６の機能を、前処理として、逆コンパイラ３０８に含めてしまうこともできる。そうすると、コード変換器３０６は単独のプログラムとしては不要により、逆コンパイラ３０８自体が、本発明の機能を組み込んだ特有のものになる。
【００３１】
あるいは、コード変換器３０６の機能を、後処理として、PHP用Java(R)バイトコード生成器２０６に組み込むことができ、そのようにしても、コード変換器３０６は単独のプログラムとしては不要になり、PHP用Java(R)バイトコード生成器２０６自体が、本発明の機能を組み込んだ特有のものになる。
【００３２】
次に、図４のフローチャートを参照して、コード変換器３０６の処理について説明する。先ず、ステップ４０２では、コード変換器３０６は、Java(R)バイトコード３０４の制御フローを解析して、Java(R)言語の制御構造に対応させ、制御ブロックに分割する処理を行う。この処理は例えば、丸山冬彦、小川宏高、松岡聡、「Javaバイトコードをデコンパイルするための効果的なアルゴリズム」情報処理学会論文誌、Vol.41, No.2. Feb. 2000、http://ci.nii.ac.jp/Detail/detail.do?LOCALID=ART0003013366 に記述されている方法を使用する。
【００３３】
次に、ステップ４０４では、制御ブロックの各命令について順次読み込み処理が行われる。この処理は、ステップ４０４から、ステップ４１６までのループとして実行される。
【００３４】
ステップ４０６では、コード変換器３０６は、対象としている命令に対し、Java(R)式の構文ノードとして対応済かどうか判断する。もしそうなら、処理は特に何もすることなく、ステップ４１６からステップ４０４に戻って、次の命令の処理へと移る。
【００３５】
ステップ４０６で、コード変換器３０６が、対象としている命令に対し、Java(R)式の構文ノードとして未対応であると判断すると、処理はステップ４０８に進み、そこで、コード変換器３０６は、単独または直後の命令とともに、Java(R)の構文木の一部として対応可能かどうか、パターンがマッチするかどうかで、調べる。
【００３６】
そして、ステップ４１０で、コード変換器３０６が、Java(R)の構文木の一部として対応可能であると判断すると、ステップ４１２に進み、そこでコード変換器３０６は、Java(R)の構文木にマッチした構文ノードを追加する。その後、ステップ４１６からステップ４０４に戻って、次の命令の処理へと移る。
【００３７】
ステップ４１０に戻って、コード変換器３０６が、Java(R)の構文木の一部として対応可能でないと判断すると、処理は、ステップ４１４に進む。このステップ４１４が、本発明の特徴的な処理を含む。
【００３８】
ステップ４１４では、コード変換器３０６は、swap、dup、pop、voidメソッド呼び出しなどのうち、スタックの状況から、他のバイトコードと組み合わせても、Java(R)の言語要素に直接対応していない命令を、ダミー・メソッド呼び出しと、ローカル変数への代入と参照、または、抽出したメソッドの呼び出しの組み合わせのパターンで置き換える処理を行う。
【００３９】
すなわち、コード変換器３０６は、Java(R)の言語要素に直接対応していない命令の置き換えルールを予め保持し、それを、ステップ４１４で適用する。
【００４０】
こうして、処理は改めてステップ４０６に戻り、Java(R)式の構文ノードとして対応済かどうかの判断が再度行われる。
【００４１】
こうして全ての命令の処理が終ると、ステップ４０４からステップ４１６までのループを脱出して、処理が完了する。
【００４２】
本発明の理解を促すために、上述のステップ４１４の命令の置き換えルールについて、より詳しく説明する。
【００４３】
ステップ４１４の処理は、Java(R)が対応可能でないコードを、次の２つの場合に分ける。
(1) Java(R)の言語要素に直接対応していない、スタック操作関連の命令を行うコードである場合。
(2) Java(R)の言語要素が直接対応していない、スタックに値を残して戻り値をもたないメソッドを呼び出すコードである場合。
【００４４】
(1)の場合とは典型的には、swap、dup、popの場合である。なお、これらのJava(R)バイトコードの命令の意味及び機能については、Java Virtual Machine Specification Second Edition by Tim Lindholm and Frank Yellin, 1999 Sun Microsystems, Inc. などの文献を参照されたい。
【００４５】
この場合、次のようなクラスが生成される。
class DFB {
static <T> T swap(Object placeholder, T preservation) {
return preservation;
}
static <T> T dup(T preservation) {
return preservation;
}
static <T> T pop(T preservation, Object erasure) {
return preservation;
}
}
【００４６】
このようなクラスDBFを以って、swap、dup、popのそれぞれの場合の変換規則について説明する。
【００４７】
まず、次のようなswapを含むバイトコードがあったとする。
...
<expr0>
<expr1>
<expr2>
swap
...
【００４８】
これは、図４のステップ４１４では、次のように変換される。
...
<expr0>
<expr1>
dup
astore 'tmp
<expr2>
invokestatic DFB.swap(Object,T):T
aload 'tmp
...
【００４９】
下記のような、dupを含むバイトコードがあったとする。
...
<expr0>
<expr1>
dup
...
【００５０】
これは、図４のステップ４１４では、次のように変換される。
...
<expr0>
<expr1>
dup
astore 'tmp
invokestatic DFB.dup(T):T
aload 'tmp
...
【００５１】
さらに、下記のような、popを含むバイトコードがあったとする。
...
<expr0>
<expr1>
pop
...
【００５２】
これは、図４のステップ４１４では、次のように変換される。
...
<expr0>
<expr1>
invokestatic DFB.pop(T,Object):T
...
【００５３】
(2) Java(R)の言語要素が直接対応していない、スタックに値を残して戻り値をもたないメソッドを呼び出すコードである場合とは例えば、
<expr1>
<expr2>
<expr3>
aload1 // runtime
invoke checkTimer(Runtime):void
invoke compare(P,P):P
のようなバイトコードの場合である。
【００５４】
この場合、コード変換器３０６は先ず、
private static <T> T call_checkTimer(T preservation, Runtime arg1) {
Op.checkTimer(arg1); // original call
return preservation;
}
を生成し、
<expr1>
<expr2>
<expr3>
aload1 // runtime
invoke <T>call_checkTimer(T,Runtime):T
invoke compare(P,P):P
と変換する。これによって、結果のソースコードでは、<expr3>が、call_checkTimer()の呼び出し式に引数として組み込まれ、<expr1>と<expr2>を一時変数に退避しなくてもよくなるため、一時変数は表れなくなる。
【００５５】
(1) Java(R)の言語要素に直接対応していない、スタック操作関連の命令を行うコードである場合について、より複雑な場合について説明する。Java(R) VMでは、スタック演算子を全て網羅すると、次のとおりである。
pop, pop2, dup, dup_x1, dup_x2, dup2, dup2_x1, dup2_x2, swap
【００５６】
このうち、pop, dup, swapは既に説明したので、その他のものについて説明する。
【００５７】
この場合は、次のようなクラスを生成する。
class DFB   {
static <T> T pop2(T pr,Object er1,Object er2)  {
return pr;
}
static <T> T dup2(T preservation, Object placeholder) {
return preservation;
}
static <T> dup_x1(T preservation, Object placeholder) {
return preservation;
}
static <T> dup2_x2(T pr, Object ph2, Object ph3, Object ph4) {
return pr;
}
}
ここでは省略されているが、pop, dup, swapのメソッドも記述されていてもよく、その内容は、既述である。
【００５８】
このようなクラスに存在のより、変換を行う例を以下、複数示す。
先ず、元のコードが<e0> <e1> <e2> pop2であった場合、下記のように変換される。
<e0> <e1> <e2> DBF.pop2
【００５９】
元のコードが<e0> <e1> <e2> dup2であった場合、下記のように変換される。
<e0> <e1> dup tmp1= <e2> dup tmp2= DBF.dup2() =tmp2 =tmp1 =tmp2
なお、以下のような変換でもよい。
<e0> <e1> dup tmp1= <e2> DBF.dup2_1() <e2> dup tmp2= DBF.dup2_2()
=tmp1 =tmp2 =tmp1 =tmp2
このように複数のパターンがありえるのは、スタック・オペレーションが複雑な場合には、ダミーのメソッドの入れ方にバリエーションが生じるからである。よって、そのバリエーションの１つを実装すればよい。
【００６０】
元のコードが<e0> <e1> <e2> dup_x1であった場合、下記のように変換される。
<e0> <e1> dup tmp1= <e2> dup tmp2= DBF.dup_x1() =tmp2 =tmp1
これは、以下のような変換でもよい。
<e0> <e1> dup tmp1= DBF.dupx1_1() <e2> dup tmp2= DBF.dupx1_2()
=tmp1 =tmp2 =tmp1
【００６１】
元のコードが<e0> <e1> <e2> <e3> dup_x2であった場合、下記のように変換される。
<e0> <e1> dup tmp1= <e2> dup tmp2= <e3> dup tmp3= <e4> dup tmp4=
DBF.dup2_x2() = tmp2 =tmp3 =tmp4 =tmp1 =tmp2
これは、以下のような変換でもよい。
<e0> <e1> dup tmp1= DBF.dupx2_x2_1() <e2> dup tmp2= .. <e3> dup tmp3= .. <e4>
dup tmp4= .. =tmp1 =tmp2 =tmp3 =tmp4 =tmp1 =tmp2
【００６２】
ところで、非特許文献１にあるような従来の技法では、
<expr0>
<expr1>
<expr2>
<expr3>
swap
invokestatic C.foo3(P,P)
invokevirtual P.foo2(P)
invokevirtual P.foo1(P)
areturn
を逆コンパイルすると、
C tmp0 = <expr0>;
P tmp1 = <expr1>;
P tmp2 = <expr2>;
return tmp0.foo1(tmp1.foo2(C.foo3(<expr3>,tmp2)));
のように一時変数が沢山残ってしまう。
【００６３】
一方、本発明によれば、
元のバイトコートの
<expr1>
<expr2>
<expr3>
swap
のところが、
<expr1>
<expr2>
dup
astore 'tmp
<expr3>
invokestatic DFB.swap(Object,T):T
aload 'tmp
と変換され、これによって、逆コンパイルされた結果のソースコードが、下記のように、一時変数が減らされた可読性の高いコードとなる。
P tmp;
return <expr0>.foo1(<expr1>.foo2(C.foo3(DBF.swap(tmp=<expr2>,<expr3>),tmp)));
【００６４】
なお、上記実施例では、PHP用バイトコード生成器によって生成されたバイトコードを変換するものとして説明がなされたが、JRuby、Jythonなど、Java(R)バイトコードを生成する任意のプログラミング言語処理系から生成されたJava(R)バイトコードに適用可能である。
【００６５】
また、Java(R)バイトコードに限らず、ターゲット言語が対応しない、スタック操作関連、あるいはスタックに値を残して戻り値をもたないメソッドを呼び出すコードを含む任意の言語処理系の中間コードに適用可能であることを、当業者なら理解するであろう。
【符号の説明】
【００６６】
１０２  システム・バス
１０４  ＣＰＵ
１０６  主記憶
１０８  ハードディスク・ドライブ
１１０  キーボード
１１２  マウス
２０２  オペレーティング・システム
２０４  Ｊａｖａ  ＶＭ
２０６  PHP用バイトコード生成器
２０８  PHPソースコード
３０６  コード変換器
【図１】
0005496792.tif 000002
【図２】
0005496792.tif 000003
【図３】
0005496792.tif 000004
【図４】
0005496792.tif 000005