iOSDC2020: J2ObjCを使ってJava資産 をiOS開発で使ってみた

iOSDC2020: J2ObjCを使ってJava資産 をiOS開発で使ってみた

iOSDC2020: J2ObjCを使ってJava資産 をiOS開発で使ってみた

https://fortee.jp/iosdc-japan-2020/proposal/a94bc318-9ba2-4c22-8e32-6be8fdcb8716

2607469010bfd7a0f0bd7546328cb01d?s=128

Akihiro Urushihara

September 19, 2020
Tweet

Transcript

  1. J2ObjCを使ってJava資産 をiOS開発で使ってみた @uakihir0

  2. 自己紹介 • Akihiro Urushihara (うるし) • @uakihir0 • 制作物 ◦

    TheWorld ◦ SocialHub
  3. J2ObjC?

  4. J2ObjC • Java → Objective-C トランスレータ • 2012年に Google から公開

    • まあまあつらい
  5. J2ObjC の採用理由は?

  6. J2ObjC の採用理由は? → 要件的に満たすものが J2ObjC だけだった

  7. SocialHub

  8. SocialHub • iOS/Android 向けのマルチ SNS クライアントアプリ ◦ SNS 周りのロジックは共通のものを使用したい ▪

    できる限り既存 OSS ライブラリを用いて楽したい
  9. SocialHub • SNS の抽象化 ◦ ライブラリに実装における複雑 性を押し込む

  10. SocialHub • iOS/Android 向けのマルチ SNS クライアントアプリ ◦ SNS 周りのロジックは共通のものを使用したい ▪

    できる限り既存 OSS ライブラリを用いて楽したい ◦ 普段使いするアプリを目指すので UI/UX 妥協しない
  11. SocialHub • iOS/Android 向けのマルチ SNS クライアントアプリ ◦ SNS 周りのロジックは共通のものを使用したい ▪

    できる限り既存 OSS ライブラリを用いて楽したい ◦ 普段使いするアプリを目指すので UI/UX 妥協しない ライブラリは共有し、UI は OS 毎にネイティブで書きたい!
  12. 採用候補

  13. Embeddinator-4000 • .NET ライブラリを他言語で使用可能にするプロジェクト ◦ Xamarin のサブプロジェクト ◦ iOS 向けに

    Objective-C に変換する機能がある ▪ ジェネリクスが使えない (#232) 制限がありこれが致命的
  14. Kotlin/Native • Kotlinを他言語/環境で使用可能にするプロジェクト ◦ 検討時の 2018 初頭では v0.6 ぐらいで知見がほぼ皆無 ◦

    既存 OSS ライブラリの利用ができない
  15. J2ObjC • Java → Objective-C トランスレータ ◦ Java の既存 OSS

    ライブラリが使用可能! ◦ Kotlin/Native にも鞍替えがギリギリ可能! ◦ 知見は国内にはほぼ無い!
  16. フレームワーク類 • UI はネイティブで追求したいので今回は検討外 ◦ Xamarin.Forms ◦ Flutter ◦ React

    Native ◦ Ionic
  17. J2ObjC Translation

  18. Hello World • Java コードを準備 • Objective-C へ変換 public class

    Main { public static void main(String[] args) { System.out.println("Hello World"); } } $ j2objc Main.java Java
  19. #include "IOSObjectArray.h" #include "J2ObjC_source.h" #include "Main.h" #include "java/io/PrintStream.h" #include "java/lang/System.h"

    @implementation Main - (instancetype)init { Main_init(self); return self; } + (void)mainWithNSStringArray:(IOSObjectArray *)args { Main_mainWithNSStringArray_(args); } // リフレクション等ためのメタデータ情報 + (const J2ObjcClassInfo *)__metadata { /* ... */ } @end void Main_init(Main *self) { /* ... */ } Main *new_Main_init() { /* ... */ } Main *create_Main_init() { /* ... */ } void Main_mainWithNSStringArray_(IOSObjectArray *args) { Main_initialize(); [((JavaIoPrintStream *) nil_chk(JreLoadStatic(JavaLangSystem, out))) printlnWithNSString:@"Hello World"]; } Objective-C (.m)
  20. 例外 • Objective-C のレイヤーで対処 @try { /* ... */ }

    @catch (JavaLangThrowable *throwable) { /* ... */ } Objective-C (.m)
  21. J2ObjC Annotations • コード変換の所々の問題についてのアプローチ

  22. 弱参照 • @Weak @Property 等を付与してメモリリークを回避 public class Main { @Weak

    private Runnable callback; Java @interface Main () { @public __unsafe_unretained id<JavaLangRunnable> callback_; } Objective-C (.m)
  23. 弱参照 • @Weak @Property 等を付与してメモリリークを回避 public class Main { @Property("weak,

    nonatomic") protected Runnable callback; Java @interface Main : NSObject { @public __unsafe_unretained id<JavaLangRunnable> callback_; } @property (weak, nonatomic) id<JavaLangRunnable> callback; Objective-C (.h)
  24. 関数名 • デフォルトでは型名が関数名に付与される public void setDate(int year, int month, int

    day){ /* … */ } Java - (void)setDateWithInt:(jint)year withInt:(jint)month withInt:(jint)day { Objective-C (.m)
  25. 関数名 • @ObjectiveCName を付与して指定 @ObjectiveCName("setDateWithYear:month:day:") public void setDate(int year, int

    month, int day){ /* … */ } Java - (void)setDateWithYear:(jint)year month:(jint)month day:(jint)day { Objective-C (.m)
  26. Nullability • @Nonnull @Nullable (jsr305) を付与して Nullability を明示 public class

    Main { public void greeting(@Nonnull String name){ /* ... */ } Java - (void)greetingWithNSString:(NSString * __nonnull)name; Objective-C (.h)
  27. Development

  28. ビルドツールの選択 • make • bazel • plugins ◦ maven-plugin ◦

    gradle-plugin
  29. gradle-plugin (j2objc-contrib/j2objc-gradle) • 面倒なことを色々やってくれるので非常に有用 ◦ ライブラリの依存関係の解決 ◦ 標準ライブラリへのリンク ◦ 各ターゲット向けのビルド

    ◦ Podfile の作成
  30. None
  31. gradle-plugin (uakihir0/j2objc-gradle) • 問題のあった箇所を修正して公開中 ◦ Gradle 4.x に対応 ▪ 2.x

    から修正 ◦ 静的ライブラリの作成方法を変更 ▪ ar → libtool に変更 (コマンド長の問題に対応)
  32. CI/CD • 開発初期は手元の MacBookPro でビルドしていた ◦ 30分ぐらいかかり半分近くバッテリーが消える ▪ しかもビルド中重くて何も出来ない

  33. CI/CD • Travis CI を使用し始める ◦ ビルド回数を気にせず Mac OS 環境が使える

    ◦ ビルド時間が 50 分までの制限がある
  34. CI/CD • GitHub Actions に変更 • Debug/Release ビルドを並列に実行

  35. Other Problems • HmacSHA1 の暗号化ができない問題 ◦ USの暗号化輸出規制の問題? 再実装して対応 • Java

    のクラスの動的読み込み問題 ◦ Class.forName(“...”) で文字列からクラスを作成される問題 ◦ 生成されそうなクラスは別途コンパイル対象に指定
  36. Release • iOS 版リリース ◦ 70MB 程で意外とコンパクト ◦ パフォーマンスは問題ない ◦

    共通ライブラリは公開中 ▪ uakihir0/SocialHub
  37. 総括

  38. BAD • 導入障壁が高い • 知見が少なくトラブルシュートが難しい • 開発サイクルがやや遅くなる

  39. GOOD • クリーンアーキテクチャに必然的になる • パフォーマンス劣化がほぼ無い • 共通コードで実装量を減らせる!

  40. Questions?