インストールと実行方法

実行環境

開発・実行用シェルスクリプトは、以下の環境でテストを行っています。

また、 dump ずみの class file の実行は、上記環境に加え、 以下の実行環境でもテストを行っています。

インストール方法

MJ のホームページから最新版をダウンロードしてください。

ダウンロードした zip ファイルを展開すると、 mj というディレクトリができます。 その下にあるディレクトリ bin を、 PATH に入れてください。

CLASSPATH の設定は不要です。

各シェルスクリプトの説明

mjc [options] *.java

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 [option] module [args...]

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 bottom m1 m2 ...

mjb は、第二引数以降で指定された module すべてを extends するような module ("bottom module" と呼びます)を、 第一引数の名前で生成し、 eppout の下に出力します。

生成された bottom module は、ソースからコンパイルしたモジュールや、 CLASSPATH 中のモジュールと全く同様に扱うことができます。 例:

% mjb m1m2 m1 m2
% mjb m1m2m3 m1m2 m3
% mj m1m2m3
...

mjb は、補完モジュールの追加は行いません。

mjball all

mjball は、直前に mjc した *.java に含まれる全ての module の bottom module を、第一引数の名前で生成し、 eppout の下に出力します。 例:

        % mjc T1.java
        % mjball all
        % mj all

このコマンドは、 mjc コマンドが生成した MJ/MJall.log というファイルの 中身を利用しています。

mjdump [option] module

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 コマンドと全く同じです。

mjclear

ディレクトリ 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 行目を実行中であることを表す。

log の見方

log の場所と出力の仕方

mjc は、 MJ/MJC.log に log を出力します。

mj, mjdump は、デフォルトでは log を出力しません。 オプションで -log を指定すれば、 MJ/MJ.log に log を出力します。

以下の節で説明する log の内容は、 MJC.log と MJ.log で共通です。

MJClassInfo

型チェックでエラーが出ると、 「ある 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 では無視されます。)

override

「ある 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

linearizedUsingModules

MJC.log か MJ.log を見れば、あるモジュールから見て、 モジュールがどのように linearize されたかを見ることができます。 log ファイルを "linearizedUsingModules for ModuleName" という文字列で検索してください。

例: m2 から見たモジュールのリスト

linearizedUsingModules for m2 :
  mj.lang.ss
  m1
  m2


mj-logo
Last updated: Dec 03 11:17:12 2001