LogCatで下の様にNoSuchMethodErrorが出るときのデバッグ方法メモ。
環境はこちらで準備したsbt。NoClassDefFoundErrorも同様にできるはず。
03-21 14:28:46.023: E/AndroidRuntime(7507): java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonFactory.createParser
上はJsonFactory.createParser が見つからない、という例。
1. クラスファイルにメソッドがあるか調べる
./target/
に生成されるjarファイルを下の様にunzipで展開し、
$ cd ./target
$ unzip classes-myapp1-compile-0.1.min.jar
...
inflating: com/fasterxml/jackson/core/JsonFactory$Feature.class
inflating: com/fasterxml/jackson/core/JsonFactory.class
...
javapコマンドでそのメソッドがあるかをチェックする。
$ javap com.fasterxml.jackson.core.JsonFactory
...
public com.fasterxml.jackson.core.JsonParser createJsonParser(java.lang.String) ...;
public com.fasterxml.jackson.core.JsonParser createJsonParser(java.io.File)...;
...
メソッド名がみつからない場合、3. 依存しているライブラリのjarファイルが古くないかをチェックし、それでもだめなら 4. proguard でそのメソッドを保持するように設定してみる。
2. dexファイルにメソッドがあるか調べる
1とは別に、dexdumpを使ってメソッド名があるかを調べることもできる。
$ cd ./target
$ $ANDROID_HOME/build-tools/19.0.0/dexdump classes-myapp1-compile-0.1.dex|grep createParser
上はcreateParser
を調べる例。grep -20 ...
として前後を表示してみるなどする。
1.と同様に、メソッド名がみつからない場合は下の 3. or 4. を当たってみる。
3. 依存しているライブラリのバージョンを調べる
- or 2.でメソッド名が見つからない場合、依存ライブラリのバージョンを調べる。下の様にsbtのコンソールで依存ライブラリのパスが取得できるので、バージョン番号を確認し古ければ更新する。
$ sbt
> show dependency-classpath
4. proguardでメソッドが取り除かれないようにする
3.が問題ない場合、proguardに-keep
オプションを追加する。
ただし、-keep
の範囲を増やすと下のようなエラーに遭遇することがある。
trouble writing output: excess write of ...
その時は、sbtを立ち上げ直すか、こちらのようにanalysisBudgetを大きな値にすると解消することが多い。なぜかは良く分かっていない。