Android
Kotlin
OkHttp3

OkHttp3をAndroidで使おうとしたときにjava.lang.ClassCastException: Bootstrap methaod returned nullが発生して初期化に失敗する


TL;DR

E/AndroidRuntime: FATAL EXCEPTION: main

Process: com.example.myapplication, PID: 12443
java.lang.BootstrapMethodError: Exception from call site #5 bootstrap method
at okhttp3.internal.Util.<clinit>(Util.java:87)
at okhttp3.internal.Util.skipLeadingAsciiWhitespace(Util.java:321)
at okhttp3.HttpUrl$Builder.parse(HttpUrl.java:1313)
at okhttp3.HttpUrl.get(HttpUrl.java:917)
at okhttp3.Request$Builder.url(Request.java:165)
at com.example.myapplication.com.example.myapplication.util.HttpUtil.httpGet(HttpUtil.kt:8)
at com.example.myapplication.MainActivity$onParallelGetButtonClick$1$1.invokeSuspend(MainActivity.kt:33)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:236)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)
Caused by: java.lang.ClassCastException: Bootstrap method returned null
at okhttp3.internal.Util.<clinit>(Util.java:87) 
at okhttp3.internal.Util.skipLeadingAsciiWhitespace(Util.java:321) 
at okhttp3.HttpUrl$Builder.parse(HttpUrl.java:1313) 
at okhttp3.HttpUrl.get(HttpUrl.java:917) 
at okhttp3.Request$Builder.url(Request.java:165) 
at com.example.myapplication.com.example.myapplication.util.HttpUtil.httpGet(HttpUtil.kt:8) 
at com.example.myapplication.MainActivity$onParallelGetButtonClick$1$1.invokeSuspend(MainActivity.kt:33) 
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32) 
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:236) 
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594) 
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60) 
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742) 

上記の類似のエラーが発生した場合は以下のオプションをbuild.gradleに追加しBuild -> Clean Projectをする

android {

compileOptions {
targetCompatibility = "8"
sourceCompatibility = "8"
}
}

https://github.com/square/okhttp/issues/4597


事の始まり

Androidは浦島太郎なので、kotlinでも触るかと思って、いろいろと試していた。

APIを叩きたいと思ったのでokhttpを導入してみた。

導入の参考に以下の記事を使わせていただいた。

https://qiita.com/jonghyo/items/bf3e4e06022eebe8e3eb

ところが、実行すると落ちてしまう。

ということで調査をしてみた。

ログには以下のような出力がされていた。

E/AndroidRuntime: FATAL EXCEPTION: main

Process: com.example.myapplication, PID: 12443
java.lang.BootstrapMethodError: Exception from call site #5 bootstrap method
at okhttp3.internal.Util.<clinit>(Util.java:87)
at okhttp3.internal.Util.skipLeadingAsciiWhitespace(Util.java:321)
at okhttp3.HttpUrl$Builder.parse(HttpUrl.java:1313)
at okhttp3.HttpUrl.get(HttpUrl.java:917)
at okhttp3.Request$Builder.url(Request.java:165)
at com.example.myapplication.com.example.myapplication.util.HttpUtil.httpGet(HttpUtil.kt:8)
at com.example.myapplication.MainActivity$onParallelGetButtonClick$1$1.invokeSuspend(MainActivity.kt:33)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:236)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)
Caused by: java.lang.ClassCastException: Bootstrap method returned null
at okhttp3.internal.Util.<clinit>(Util.java:87) 

java.lang.BootstrapMethoderrorって何だろう?と思って公式のドキュメントも見てみたが動的読み込みに失敗したときにおこるということ以上の事はよくわからない。

デバッグしてもなぜか本当に落ちる。よくわからない。


仕方がないのでググる

https://github.com/square/okhttp/issues/4597

すると上記のissueが見つかった。

JakeWhartonさん曰く3.13以上のOkHttpではJava8機能をビルド時に有効にする必要があるとのこと。


OkHttp requires that you enable Java 8 in your builds to function as of 3.13 and newer.


とのことなので、JakeWhartonさんの書いているコードを仕込む。

android {

compileOptions {
targetCompatibility = "8"
sourceCompatibility = "8"
}
}

これで動くぞやれやれと思っていたら動かなくて焦ったのですが、ちょっと読み進めると動かないよーって言ってる人がいてそうそう動かないよ。とか思ってたのですが、

上記のissueの下の方でeddexさんがbuild.gradleを変更したらBuild -> clean buildを忘れずにやってね。と書いていました。

試してみたところ無事動いてめでたしめでたしという感じでした。

因みに久しぶりすぎて、マニフェストに<uses-permission android:name="android.permission.INTERNET" />足し忘れてまたはまってました。

みんな上記のオプションを仕込むのが当たり前だから、話題になってないんだろうなと思います。