RoboVMは、JavaのコードをARMやX86のバイナリに出力してくれるすごいロボです。
Java+libGDXで作ったAndroid用ゲームをRoboVMでiOS用バイナリ出力してAndroid/iOSマルチ対応作戦を目論んでいます。
が、いざRoboVMにかけたら「リフレクションなんか対応してるわけないだろJK」とか言われても困るので検証してみました。
#とりあえずiOSアプリが生成できるか検証
以下のサイトを参考に、iOSアプリのソースをJavaで書いてRoboVMでiOS用バイナリーを生成、シミュレーターで実行してみました。
JavaでiOSアプリ開発 RoboVM + eclipse
動いた!
「Click」というボタンをクリックすると数字がカウントアップされていきます。
XCodeのバージョンは、バージョン 5.1.1
iOSシミュレーターは、バージョン 7.1 (463.9.41)
OS Xは、バージョン 10.9.2
JDKは、バージョン 1.7.0_40
RoboVMは、バージョン 0.0.11
現時点での最新バージョン(ver.0.0.11)ではファイルネームが変わり、RoboVMのダウンロードとインストールの手順は以下のようになりますので注意。
curl http://download.robovm.org/robovm-0.0.11.tar.gz > robovm.tar.gz
sudo tar xvfz robovm.tar.gz -C /opt
sudo ln -s /opt/robovm-0.0.11 /opt/robovm
#本題:リフレクションなどが動くかテスト
検証用ソース
import java.io.Serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class HelloWorld implements Serializable {
private static final long serialVersionUID = 1L;
String str = "HELLO!";
int num = 123456;
int num2 = 65;
float pi = 3.14159265f;
public enum Sound {
ARRIVAL1("se_puu10.ogg"),
ARRIVAL2("se_puu37.ogg"),
ARRIVAL3("se_puu26.ogg");
private String filename_;
private Sound(String filename) {
filename_ = filename;
}
public String getFilename() {
return filename_;
}
};
public static void main(String[] args) {
System.out.println("Hello world!");
HelloWorld hello = new HelloWorld();
// serialize test
System.out.println("serialize and sate serialize.dat");
try {
FileOutputStream fos = new FileOutputStream("serialize.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(hello);
oos.close();
} catch (Exception ex) {}
// reflection test
for (Field field: hello.getClass().getDeclaredFields()) {
if (!Modifier.isStatic(field.getModifiers())) {
System.out.println("name:" + field.getName() + " type:" + field.getType());
}
}
// enum test
for (Sound sound: Sound.values()) {
System.out.println("sound filename:" + sound.getFilename());
}
}
}
実行結果
解説
シリアライズ
コード
public class HelloWorld implements Serializable {
private static final long serialVersionUID = 1L;
String str = "HELLO!";
int num = 123456;
int num2 = 65;
float pi = 3.14159265f;
(中略)
// serialize test
System.out.println("serialize and sate serialize.dat");
try {
FileOutputStream fos = new FileOutputStream("serialize.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(hello);
oos.close();
} catch (Exception ex) {}
HelloWorld クラスをシリアライズしてファイル「serialize.dat」に出力しています。
出力結果は以下のとおりです。
0000000 ac ed 00 05 73 72 00 0a 48 65 6c 6c 6f 57 6f 72
0000020 6c 64 00 00 00 00 00 00 00 01 02 00 04 49 00 03
0000040 6e 75 6d 49 00 04 6e 75 6d 32 46 00 02 70 69 4c
0000060 00 03 73 74 72 74 00 12 4c 6a 61 76 61 2f 6c 61
0000100 6e 67 2f 53 74 72 69 6e 67 3b 78 70 00 01 e2 40
0000120 00 00 00 41 40 49 0f db 74 00 06 48 45 4c 4c 4f
0000140 21
当たり前ですが、Javaとして実行した場合と同じ結果になりました。
リフレクション
// reflection test
for (Field field: hello.getClass().getDeclaredFields()) {
if (!Modifier.isStatic(field.getModifiers())) {
System.out.println("name:" + field.getName() + " type:" + field.getType());
}
}
リフレクションでHelloWorldクラスのインスタンス「hello」のフィールドを列挙して表示しています。(フィールド名と型)
name:pi type:float
name:num2 type:int
name:num type:int
name:str type:class java.lang.String
Javaで実行したときと同じ結果になりました。
Enumに独自メソッド実装
public enum Sound {
ARRIVAL1("se_puu10.ogg"),
ARRIVAL2("se_puu37.ogg"),
ARRIVAL3("se_puu26.ogg");
private String filename_;
private Sound(String filename) {
filename_ = filename;
}
public String getFilename() {
return filename_;
}
};
(略)
// enum test
for (Sound sound: Sound.values()) {
System.out.println("sound filename:" + sound.getFilename());
}
列挙型Sound にコンストラクタとメンバー変数を追加し、文字列型でfilename_メンバー変数を追加しました。
追加したgetFilename()メソッドで、filenameメンバーの値を取得して表示しています。
sound filename:se_puu10.ogg
sound filename:se_puu37.ogg
sound filename:se_puu26.ogg
Javaで実行したときと同じ結果になりました。
追記:弱参照
import java.lang.ref.WeakReference;
(略)
// WeakReference
WeakReference<HelloWorld> helloRef = new WeakReference<HelloWorld>(hello);
HelloWorld hello2 = helloRef.get();
System.out.println("hello2.str:" + hello2.str);
WeakReferenceもOK!
hello2.str:HELLO!
とりあえずコレで安心して、Android版を作ることが出来そうです。