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

Scala2.10.x bytecode problems in Android

Jun 04, 2015

Download

Technology

Taisuke Oe
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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日木曜日