トップ 一覧 Farm 検索 ヘルプ RSS ログイン

Diary/2007-8-11の変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!!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<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();
   }
 }