Androidリリースビルドでjava.lang.IncompatibleClassChangeError

Androidアプリ開発しているとデバッグビルドでは問題ないけど、リリースビルドで動かしていると突然クラッシュすることよくあると思います。

classのシュリンキング、難読化が原因だったりしますが、今回は java.lang.IncompatibleClassChangeError どうも、コンパイル時のclassと実行時のクラスが違う時に発生しているらしい。

具体的なエラーログは以下だった

Caused by: java.lang.IncompatibleClassChangeError: 
Class 'org.apache.http.message.BufferedHeader' does not implement interface 'org.apache.http.NameValuePair' in call to 'java.lang.String org.apache.http.NameValuePair.getValue()' 
(declaration of 'hogehoge.hoge.sdk' appears in /data/app/jp.co.hoge.hogehugahuga==/base.apk:classes3.dex)

BufferedHeader というのが NameValuePairインターフェース のgetValue()メソッドを実装していないらしい。

このエラーを吐いていたのがgradleで読み込んでいるjarのライブラリだった。

productionImplementation files('/libs/hogehoge.jar')

このjarビルド時(コンパイル時)にBufferedHeaderに依存していた何らかのclassが、実行時に参照しているBuffreredHeaderと互換性がない(Incompatible)という旨のエラー内容だと理解した。

このjar自体古いみたいなので、graldeで読み込んでいる他の新しめのライブラリとかなり剥離しているんだと予想した。

“`org.apache.http.message.BufferedHeader“`
はどのライブラリなのかググると、どうもapache httpcoreモジュールに入っているclassみたいだ。

302 Found
$ ./gradlew :app:dependencies

で調べるとそれらしき、ライブラリが見つかった。

なのでこれをexcludeするには apacheのhttpcoreモジュールを指定すれば良いみたいだ。
いろいろな他のライブラリが依存していそうでそれぞれにexcludeしてみても除外できなかったため、以下のようにして全体的に除外してみる。

configurations {
        all*.exclude (group: 'org.apache.httpcomponents', module: 'httpcore' )
    }

これでエラーでず、クラッシュしなくなった訳だが、all*.excludeで除外してもよいのか、他の影響が気になるが、エラー出ていたライブラリでapacheのhttpclientを使用していたため、下記宣言していた。

        useLibrary  'org.apache.http.legacy'

そのため、他のライブラリでは使っていないものと思われ、all.excludeでも大丈夫だと思う。
そもそも このlegacyオプション使用していたので、all
.excludeが必要だったのかもとも思う。

Comments

タイトルとURLをコピーしました