ProguardでJNIのnativeメソッドが削除された
アプリが起動しないという連絡を受け、確認したログを元にパッケージから取り出したclassをjavapにかけた。やはりソースにあるメソッドが消えている... どんなオプションでビルドしたらこんなことになるんだろう。
2011-01-13 21:58:37そーいや、アプリが起動できなかった件、Proguardのせいだった。Proguardが未使用なPublicメソッドを削除→そのメソッドが呼ぶprivate nativeなメソッドも削除。でJava側は削除されるがJNIで呼ばれるC側は変更なし。
2011-01-15 00:22:08呼ばれないなら問題無いのでは? @l_b__ アプリが起動できなかった件、Proguardのせいだった。Proguardが未使用なPublicメソッドを削除→そのメソッドが呼ぶprivate nativeなメソッドも削除。でJava側は削除されるがJNIで呼ばれるC側は変更なし。
2011-01-15 00:27:37で、アプリを起動→DalvikがJNI_OnLoadを実行→レジストされているCとJavaの関数をチェック→C側はあるが、対応するJava側が無い→エラー。起動できませんという罠に嵌っていたのでした。Proguardが何をどこまでやるのか調べておかないとなあ。
2011-01-15 00:24:25なるほど。 @l_b__ で、アプリを起動→DalvikがJNI_OnLoadを実行→レジストされているCとJavaの関数をチェック→C側はあるが、対応するJava側が無い→エラー。起動できませんという罠に嵌っていたのでした。Proguardが何をどこまでやるのか調べておかないと
2011-01-15 00:29:02ほうほう。 @Tennetiss うちもNDKでの開発にVS使ってますなあ / I learned something today: Android Debugging, Visual Studio style! http://htn.to/gRak3x
2011-01-15 00:31:52明示的に登録する方法もある。これもJNIの正規な方法でDalvik独自じゃない。 @kmt_t JavaのJNIって確かメソッド名の規約でJava側とネイティブ側を結びつけてるんじゃなかったっけ。Dalvikって違うの?
2011-01-15 00:33:47Dalvikは通常のJNIの他に、NativeとJavaを紐付けてレジストする方法もあるんですよ。RT @kmt_t: JavaのJNIって確かメソッド名の規約でJava側とネイティブ側を結びつけてるんじゃなかったっけ。Dalvikって違うの?
2011-01-15 00:34:10@tetsu_koba さん、@l_b_ さん、ご教授ありがとうございます。なるほど、JNIまわりは全然ソースが読めてないので知りませんでした。
2011-01-15 00:37:05正規な仕様だったのか。RT @tetsu_koba: 明示的に登録する方法もある。これもJNIの正規な方法でDalvik独自じゃない。 @kmt_t JavaのJNIって確かメソッド名の規約でJava側とネイティブ側を結びつけてるんじゃなかったっけ。Dalvikって違うの?
2011-01-15 00:39:33@kmt_t で、C関数とJavaメソッドを紐付けた配列を記述しておいたのですが、Java側がProguardに消されちゃってDalvikの起動時チェックにエラーだったんです。関数規約での宣言なら起動時チェックは無いのでエラー起きなかったと思います。
2011-01-15 00:42:11そうだね。 @l_b__ @kmt_t @kmt_t で、C関数とJavaメソッドを紐付けた配列を記述しておいたのですが、Java側がProguardに消されちゃってDalvikの起動時チェックにエラーだったんです。関数規約での宣言なら起動時チェックは無いのでエラー起きなかったと
2011-01-15 00:44:05RegisterNativesで登録するならJNI_OnLoadの中でやれって感じかな。 @kmt_t @l_b__ JNI_OnLoadで>RegisterNativesしろって書いてありますね。
2011-01-15 00:49:20@kmt_t 使ってないからってデフォルトでPublicメソッドを消すのってどうよって感じです。それでもJavaだけなら問題なかったんですが、JNI周りはやはり難読化ツールの嵌るところですね。
2011-01-15 00:49:27その辺りはFrameworkのJNI使っているところにたくさんサンプルになる実装ありますね。@tetsu_koba: RegisterNativesで登録するならJNI_OnLoadの中でやれって感じかな。 @kmt_t JNI_OnLoadで>RegisterNativesしろ
2011-01-15 00:51:55DalvikVMのコアクラスのnativeメソッドは全てRegisterNativesの方法を使っている。こっちだとダイナミックリンカの機能を使わないので、スタティックリンクしている場合でも大丈夫。命名規則の方法だと必ずダイナミックリンクライブラリにする必要があるはず。
2011-01-15 00:52:59@tetsu_koba さん、そうですね(^^; JNIの仕様ってかならずしも自然な感じではない気がします。実装の都合で用意されているAPIも多い印象ですね。
2011-01-15 00:59:2210数年前にダイナミックリンクのしくみがないOSの上にJavaVMの載せてJNIを実装したことがある。そのときは関数名から関数のアドレスを求める仕組みを独自でつくった。
2011-01-15 00:59:50横浜在住Gadget&Android好き、星を見る人、よく食べよく呑む、自転車通勤RaleighRF7乗り、Enigma&DeepForest好き、歴史(日本・欧州・中国)小説&SF好き、立ち技格闘技好き、横浜AndroidPF部