トップ 差分 一覧 Farm ソース 検索 ヘルプ PDF RSS ログイン

Diary/2007-8-11

 gcjで遊んでみる

[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を使用
テストコードは、最後に示しているものを利用。



一度にコンパイル

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<Integer> list = new ArrayList<Integer>();
    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();
  }
}