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