開発・実行用シェルスクリプトは、以下の環境でテストを行っています。
また、 dump ずみの class file の実行は、上記環境に加え、 以下の実行環境でもテストを行っています。
MJ のホームページから最新版をダウンロードしてください。
ダウンロードした zip ファイルを展開すると、 mj というディレクトリができます。 その下にあるディレクトリ bin を、 PATH に入れてください。
CLASSPATH の設定は不要です。
mjc は、引数で指定されたソースファイルをコンパイルし、 結果のクラスファイルを eppout の下に作ります。
mjc は、実行ログを MJ/MJC.log に出力します。
javac のような「必要なソースファイルを自動的にコンパイルする」という 機能は、 mjc にはありません。 コンパイルしたいソースファイルは、すべて、 mjc の引数に指定しなければなりません。
mjc は、コンパイルしたソースファイル中に含まれる全てのモジュール名を、 MJ/MJall.log に書き出します。 このファイルは、 mjball コマンドで利用されます。
option として、 -Jxxx と -Exxx が任意の個数、指定できます。
-Jxxx は、 xxx を java のオプションとして渡します。
-Exxx は、 xxx を epp のオプションとして渡します。
例:
% mjc -J-mx512m -J-Ddebug=true -E-plug-in -Ejp.go.etl.epp.typeof *.java
mjc -J-Dmj.emitToSingleFile=true *.java とやると、入力ファイルごとに、変換結果が 1つの出力ファイルにまとめて出力されます。 (このオプションをつけないと、クラスごとに別の出力ファイルに 分けて出力されます。) mjc のプリプロセッサが出力する Java ソースコードを見てみたい場合に 利用してください。 なお、この出力ファイルは javac を通らないので、このコマンドは コンパイルエラーで終了します。
mjc -h は、オプションの簡単な説明を表示します。
注意 : クラスの数が多くなると、 cygwin ではコンパイルできなくなる かもしれないので、注意してください。( javac に渡す引数が長くなるため。)
mj は、引数で指定された module ( "selected module" と呼びます)を JavaVM に load して実行します。 このときリンカーは、 selected module が依存するモジュールと、 必要な補完モジュールを CLASSPATH から自動的に検索し、リンクします。
mj は、 eppout というディレクトリがなくても実行することができます。
option として、 -Jxxx 、 -Exxx 、-s m が任意の個数、指定できます。
-Jxxx は、 xxx を java のオプションとして渡します。
-Exxx は、 xxx を epp のオプションとして渡します。
-s m は、 m を selected module のリストに加えます。
-log が指定されると、MJ/MJ.log にログを出力します。
-h は、オプションの簡単な説明を表示します。
args... は、そのまま void main(String[] args) に渡されます。
selected module の指定の順序は、実行に影響を与えません。 リンカーは、言語仕様によって決められたルールに従って 全てのモジュールを linearize してから実行するからです。
mjb は、第二引数以降で指定された module すべてを extends するような module ("bottom module" と呼びます)を、 第一引数の名前で生成し、 eppout の下に出力します。
生成された bottom module は、ソースからコンパイルしたモジュールや、 CLASSPATH 中のモジュールと全く同様に扱うことができます。 例:
% mjb m1m2 m1 m2 % mjb m1m2m3 m1m2 m3 % mj m1m2m3 ...
mjb は、補完モジュールの追加は行いません。
mjball は、直前に mjc した *.java に含まれる全ての module の bottom module を、第一引数の名前で生成し、 eppout の下に出力します。 例:
% mjc T1.java % mjball all % mj all
このコマンドは、 mjc コマンドが生成した MJ/MJall.log というファイルの 中身を利用しています。
mjdump は、引数で指定された selected module および、 それが依存するモジュールと必要な補完モジュールをすべてリンクして、 その結果できたクラスファイルを普通の Java アプリケーションの形で、 ディレクトリ eppout/mjdump の下に出力します。 dump されたアプリケーションは、 java mjc.Start とやって実行することができます。
使用例:
% mjdump all ... % cd eppout/mjdump % java mjc.Start
mjc.Start には、引数を与えることもできます。 引数は main(String[]) に渡されます。
option として、 -Jxxx 、 -Exxx 、 -s m が任意の個数、指定できます。
意味は、 mj コマンドと全く同じです。
ディレクトリ eppout の下の *.java, *.class を消したいときは、 mjclear を用います。
% mjclear Checking files under "eppout"... Start removing files under eppout... Done. No Java files were translated. %
このコマンドは、 *.java ファイルが EPP によって自動生成されたものかどうかを、 ファイルの先頭を読んで判定します。 EPP が生成したものではない *.java ファイルや、 *.java 、 *.class 以外のファイルが1つでも eppout の下にある場合は、 mjclear はファイルを一切削除せずに、メッセージを出して終了します。
% mjclear Checking files under "eppout"...
The followings are not generated files. eppout/memo.txt
No files were removed. Please remove them manually.
・スタックトレースの例
java.lang.Error: test! at m3._Delta_ss_SS.m1_testA(_Delta_ss_SS.java:114) at m1._Delta_ss_SS.main(_Delta_ss_SS.java:42) at m2._Delta_ss_SS.main(_Delta_ss_SS.java:76) at m3._Delta_ss_SS.main(_Delta_ss_SS.java:106) at merge._Delta_ss_SS.main(_Delta_ss_SS.java:168) at anonymousClass._Delta_ss_SS.main(_Delta_ss_SS.java:205) at very.longlong.module.name._Delta_ss_SS.main(_Delta_ss_SS.java:249) at very.longlong.another.module.name._Delta_ss_SS.main(_Delta_ss_SS.java:262) at mjc.MJLinker.startMain(MJLinker.java:186) at mjc.MJLinker.doLink(MJLinker.java:100) at mjc.MJC_Epp_globalProcessAfterTypeCheckingPass.call(PlugIn.java:123) at jp.go.etl.epp.epp.FileInfo.globalProcessAfterTypeCheckingPass(FileInfo.java:175) at jp.go.etl.epp.epp.Epp.globalEpp(Epp.java:470) at jp.go.etl.epp.epp.Epp.processFiles(Epp.java:339) at jp.go.etl.epp.epp.Epp.processFilesAndCatchEppUserError(Epp.java:325) at jp.go.etl.epp.epp.Epp.eppMain(Epp.java:55) at jp.go.etl.epp.epp.Epp.main(Epp.java:22) test! java.lang.Error: Error during executing main.
・ (Compiled Code) と出て行番号が出ない場合は、 JIT を off にすれば 出るようになります。 例:
% ( setenv MJJAVA 'java -Djava.compiler=' ; mj all )
・ mjc.MJLinker.startMain(MJLinker.java:186) という行よりも上の部分が、 アプリケーションの実行部分です。この行以下は無視してください。
・各行は、次のように読みます。
at m3._Delta_ss_SS.m1_testA(_Delta_ss_SS.java:114)
-- *1
----- *2
-------- *3
-- -------------- *4
*1 は、モジュール m3 の中のメソッドを実行中であることを表す。 *2 は、クラス ss.SS のメソッドを実行中であることを表す。 *3 は、m1::tsetA という名前のメソッドを実行中であることを表す。 *4 は、モジュール m3 の中のクラス ss.SS の 114 行目を実行中であることを表す。
mjc は、 MJ/MJC.log に log を出力します。
mj, mjdump は、デフォルトでは log を出力しません。 オプションで -log を指定すれば、 MJ/MJ.log に log を出力します。
以下の節で説明する log の内容は、 MJC.log と MJ.log で共通です。
型チェックでエラーが出ると、 「ある module から見て、クラス C がどのようなメソッドを持っているか」が 知りたくなります。 こういう場合は、 MJ/MJC.log または MJ/MJ.log の中から MJClassInfo の出力結果を探してください。
そのためには、 log ファイルの中を、 "End initializing MJClassInfo of ClassFullName at ModuleName " という文字列で検索します。
例: all というモジュールから見た、 merge0.C というクラスの MJClassInfo
End initializing MJClassInfo of merge0.C at all . MJClassInfo: class merge0.C extends java.lang.Object { int merge1::x int merge2::x public final native void java::wait(long) throws java.lang.InterruptedExceptio n public final void java::wait(long, int) throws java.lang.InterruptedException public final void java::wait() throws java.lang.InterruptedException protected void java::finalize() throws java.lang.Throwable public native int java::hashCode() public final native void java::notifyAll() public final native void java::notify() public final native java.lang.Class java::getClass() int merge1::foo() int merge2::foo() protected native java.lang.Object java::clone() throws java.lang.CloneNotSuppo rtedException public boolean java::equals(java.lang.Object) public java.lang.String java::toString() }
( public、protected という modifier がついていますが、 MJ では無視されます。)
「ある module から見て、どのメソッドがどのメソッドを override しているか」が 知りたくなることもあります。 MJClassInfo を作る過程で、 override の処理をやっているはずなので、 その処理の log 出力を見てください。
例: all というモジュールから見た mj.SubA というクラスのメソッドの override の処理の過程
Start initializing MJClassInfo of m1.SubA at all . Start initializing MJClassInfo of m1.A at all . m1.A#m1::a at m2 overrides m1.A#m1::a at m1 . m1.A#m1::a at m3 overrides m1.A#m1::a at m2 . End initializing MJClassInfo of m1.A at all . MJClassInfo: ( mj.A の MJClassInfo の出力、省略。) m1.SubA#m1::a at m1 overrides m1.A#m1::a at m3 . m1.SubA#m1::a at m2 overrides m1.SubA#m1::a at m1 . m1.SubA#m2::m2a at m2 overrides m1.A#m2::m2a at m2 . m1.SubA#m1::a at m3 overrides m1.SubA#m1::a at m2 . m1.SubA#m3::m3a at m3 overrides m1.A#m3::m3a at m3 . End initializing MJClassInfo of m1.SubA at all .
この log を見れば、例えば m1::a というメソッドは次の順で override されていることが、一応わかります。
m1.A#m1::a at m1 m1.A#m1::a at m2 m1.A#m1::a at m3 m1.SubA#m1::a at m1 m1.SubA#m1::a at m2 m1.SubA#m1::a at m3
MJC.log か MJ.log を見れば、あるモジュールから見て、 モジュールがどのように linearize されたかを見ることができます。 log ファイルを "linearizedUsingModules for ModuleName" という文字列で検索してください。
例: m2 から見たモジュールのリスト
linearizedUsingModules for m2 : mj.lang.ss m1 m2
Last updated:
Dec 03 11:17:12 2001
|