!!gcjで遊んでみる {{category Java}} gcjについては↓を読んでみる。 http://gcc.gnu.org/java/ http://www.shudo.net/article/Fedora-Core-Expert-200507-GCJ/ http://www.asahi-net.or.jp/~wg5k-ickw/html/online/gcj-3.2.1/gcj-ja.html で、パッケージとかJarとか動的ロードとかの扱いを試してみた。 gccは、FreeBSD 6.2-RELEASE上でコンパイルしたgcc-4.2.1を使用 テストコードは、最後に示しているものを利用。 {{outline}} !一度にコンパイル gcj --main=test.Test test/*.java !中間ファイルを作ってコンパイル gcj -c test/Hoge.java gcj -c test/Test.java gcj --main=test.Test *.o パッケージのルートが"."でない場合(たとえばsrc/とか)は gcj -Isrc -c src/test/Test.java gcj -Isrc -c src/test/Hoge.java !Classファイルからオブジェクトコードを作る javac test/*.java gcj -c test/Test.class gcj -c test/Hoge.class gcj -c test/Test\$TestInner.class gcj --main=test.Test *.o 内部クラスのオブジェクトコードを作るのも忘れないように 外部のパッケージを使っている場合も、そのjarやフォルダを-Iで指定する。 !jarからオブジェクトコードを作る javac test/*.java jar cvf test.jar test/*.class gcj -c test.jar gcj --main=test.Test test.o jarファイルはそのままオブジェクトコードになる !shared objectにする gcj -o libHoge.so -shared test/Hoge.java gcj --main=test.Test test/Test.java -L. -lHoge jarファイルをshared objectにすることもできる jar cvf test.jar test/*.class gcj -o libTest.so -shared test.jar !動的ロード(1) javac test/Hoge.java javac test/Test.java gcj --main=Loader Loader.java ロードするクラスへ正しくアクセスできないとだめ。 javaやgijと違って起動時にclasspathを設定できるわけではないので、 外部のjarを利用したいなら、 パッケージのjarごとshared objectにして動的リンクするか、 自分で管理する必要がある? !動的ロード(2) gcj -o libHoge.so -shared test/Hoge.java javac test/Test.java gcj --main=Loader Loader.java -L. -lHoge 実行時に、libHoge.soがLD_LIBRARYPATHで参照できる必要がある !動的ロードの優先順位 gcj -o libHoge.so -shared test/Hoge.java javac test/Test.java とした後で、 Hoge.javaのコンストラクタで、クラス名を表示する前に System.out.println("Modified"); と表示させるように変更して javac test/Hoge.java とクラスを作る。で、次の二つを実行 ::リンクしない gcj --main=Loader Loader.java 実行結果は、 miyo@vmouton:% ./a.out modified test.Hoge test.Test test.Test$TestInner modified test.Hoge Hogeを変更しているので、当然。 ::libHoge.soをリンクする gcj --main=Loader Loader.java -L. -lHoge 実行結果は、 miyo@vmouton:% ./a.out test.Hoge test.Test test.Test$TestInner test.Hoge つまりLoaderはもちろん、Testの方でも コンパイル時に動的リンクしたlibHoge.soが優先される。 # 何か設定とかプログラムで変更できるのかな? !1.5のコード gcjでは、1.5のコード、ジェネリクスや、 イテレーション構文、オートボキシングのあるコードはコンパイルできません。 が、一度javacを使ってクラスファイルに落とすことで、gcjに通せます。 import java.util.*; public class Test5{ public static void main(String[] args){ ArrayList list = new ArrayList(); for(int i = 0; i < 10; i++){ list.add(i); } for(Integer s: list){ System.out.println(s); } } } なら、 javac Test5.java gcj --main=Test5 Test5.class とか !テストコード ::test/Hoge.java package test; public class Hoge{ public Hoge(){ //System.out.println("modified"); System.out.println(this.getClass().getName()); } } ::test/Test.java public class Test{ public Test(){ System.out.println(this.getClass().getName()); new TestInner(); new Hoge(); } class TestInner{ public TestInner(){ System.out.println(this.getClass().getName()); } } public static void main(String[] args){ new Test(); } } ::Loader.java public class Loader{ public static void main(String[] args) throws Exception{ ClassLoader.getSystemClassLoader().loadClass("test.Hoge").newInstance(); ClassLoader.getSystemClassLoader().loadClass("test.Test").newInstance(); } }