19
Scala2.10 bytecode problem hemplant Inc. @OE_uia / Taisuke Oe 13314日木曜日

Scala2.10.x bytecode problems in Android

Embed Size (px)

Citation preview

Page 1: Scala2.10.x bytecode problems in Android

Scala2.10bytecode problem

hemplant Inc. @OE_uia / Taisuke Oe

13年3月14日木曜日

Page 2: Scala2.10.x bytecode problems in Android

Q.以下のソースコードをコンパイルした際のbytecode、Scala2.10と2.9で

違うってご存知でしたか?

13年3月14日木曜日

Page 3: Scala2.10.x bytecode problems in Android

Scala2.9.xjavap -c Hello\$delayedInit\$body------public final class Hello$delayedInit$body extends scala.runtime.AbstractFunction0 implements scala.ScalaObject{public final java.lang.Object apply(); Code: 0:new#7; //class Duck 3:dup 4:invokespecial#12; //Method Duck."<init>":()V 7:invokevirtual#15; //Method Duck.fly:()V 10:getstatic#21; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit; 13:areturn

......

}

13年3月14日木曜日

Page 4: Scala2.10.x bytecode problems in Android

Scala2.10.xjavap -c Hello\$delayedInit\$body------ public final class Hello$delayedInit$body extends scala.runtime.AbstractFunction0{public final java.lang.Object apply(); Code: 0:new#9; //class Duck 3:dup 4:invokespecial#13; //Method Duck."<init>":()V 7:invokevirtual#18; //Method Bird.fly:()V 10:getstatic#24; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit; 13:areturn

.....

}

13年3月14日木曜日

Page 5: Scala2.10.x bytecode problems in Android

Scala2.9.xでは子クラス(Duck)のメソッドとして呼び出すbytecodeを生成するのに対し 7:invokevirtual#15; //Method Duck.fly:()V

Scala 2.10.xではメソッドを実装した親クラス(Bird)のメソッドとして呼び出すbytecodeが生成される。 7:invokevirtual#18; //Method Bird.fly:()V

13年3月14日木曜日

Page 6: Scala2.10.x bytecode problems in Android

何か問題でも?Android 4.1以上のライブラリ

+Scala2.10.x 

+Android4.0以下の端末

deNoSuchMethodError

13年3月14日木曜日

Page 7: Scala2.10.x bytecode problems in Android

前提として• Android APIのクラスファイルは実行ファイル(apk)には含まれず、Android端末内のものを参照する。

• AndroidのtargetSDKversionより、minSDKversionが低いことはよくあります。 (例: Android 4.1以上の場合は4.1で追加された「ほげほげView」を使うけど、Android 2.3では他のViewで代替する、など。)

13年3月14日木曜日

Page 8: Scala2.10.x bytecode problems in Android

Android 4.1以上のライブラリ+

Scala2.10.x +

Android4.0以下の端末だと....

何か問題でも?

13年3月14日木曜日

Page 9: Scala2.10.x bytecode problems in Android

SQLiteDatabaseを閉じれない!!

threadid=1: thread exiting with uncaught exception (group=0x40abd210)FATAL EXCEPTION: mainjava.lang.NoSuchMethodError: android.database.sqlite.SQLiteClosable.closeat com.hemplant.demo.no_such_method_in_2_10.DemoActivity.onCreate(DemoActivity.scala:18)at android.app.Activity.performCreate(Activity.java:4465)at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)....

13年3月14日木曜日

Page 10: Scala2.10.x bytecode problems in Android

Why? SQLiteDatabase・Android1.5からcloseメソッドを持っている。・closeメソッドを実装しているクラスが、Android4.1から変更された。

13年3月14日木曜日

Page 11: Scala2.10.x bytecode problems in Android

Android4.0までは、SQLiteDatabaseでcloseメソッドが実装されていた。

13年3月14日木曜日

Page 12: Scala2.10.x bytecode problems in Android

Android4.1からはSQLiteDatabaseの親クラスSQLiteClosableでcloseメソッドが実装

され、SQLiteDatabaseは継承したcloseメソッドを使用するように変更された。

13年3月14日木曜日

Page 13: Scala2.10.x bytecode problems in Android

逆に言えばAndroid4.0までは、SQLiteDatabaseの親クラス

SQLiteClosableにcloseメソッドは無かった。(名前がClosableなのに!)

13年3月14日木曜日

Page 14: Scala2.10.x bytecode problems in Android

~Android 4.0 Android4.1~

SQLiteClosable.close × ◯

SQLiteDatabase.close ◯ 継承

closeメソッドの実装まとめ

13年3月14日木曜日

Page 15: Scala2.10.x bytecode problems in Android

ここでもう一度

13年3月14日木曜日

Page 16: Scala2.10.x bytecode problems in Android

Scala2.9.xでは子クラス(Duck)のメソッドとして呼び出すbytecodeを生成するのに対し 7:invokevirtual#15; //Method Duck.fly:()V

Scala 2.10.xではメソッドを実装した親クラス(Bird)のメソッドとして呼び出すbytecodeが生成される。 7:invokevirtual#18; //Method Bird.fly:()V

13年3月14日木曜日

Page 17: Scala2.10.x bytecode problems in Android

(Android4.1以上をtargetにすると)

Scala2.9.xだとSQLiteDatabaseのメソッドとして呼び出すbytecodeを生成するのに対し、 58:invokevirtual#55; //Method android/database/sqlite/SQLiteDatabase.close:()V

Scala 2.10.xだとSQLiteClosable(closeを実装した親クラス)のメソッドとして呼び出すbytecodeを生成。=> Android4.0以下には無い!!

=> NoSuchMethodError 58:invokevirtual#55; //Method android/database/sqlite/SQLiteClosable.close:()V

13年3月14日木曜日

Page 18: Scala2.10.x bytecode problems in Android

まとめ• Scala2.10からは、そのメソッドを実装したクラス(当該インスタンスのクラスor親クラス)のメソッドとしてinvokevirtualするbytecodeが生成される。

• 実行環境と開発環境のクラスファイルが一致しないケースで、かつメソッドを実装したクラスに違いがあると、一見イミフなNoSuchMethodErrorを吐き出すので注意。

• 具体的には、Android4.1以上をtarget SDK versionにしたら、Scala2.10.xを使わないか、minSdkVersionも4.1

以上を指定すること。

13年3月14日木曜日

Page 19: Scala2.10.x bytecode problems in Android

最後に•Scala2.10.xで、なぜこんな変更をされたのか、経緯をご存知の方教えてください! (当面codegenしてissuesに上げつつ、ソースのdiff追います。)

•再現用プロジェクトLink:

• https://github.com/taisukeoe/scala_2_10_android_error

13年3月14日木曜日