diff --git a/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt index dd39210d25..5cdaff3ff6 100644 --- a/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt +++ b/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt @@ -4,6 +4,7 @@ package kotlinx.coroutines +import kotlinx.coroutines.internal.* import java.util.* import kotlin.coroutines.* @@ -17,14 +18,29 @@ import kotlin.coroutines.* * We are explicitly using the `ServiceLoader.load(MyClass::class.java, MyClass::class.java.classLoader).iterator()` * form of the ServiceLoader call to enable R8 optimization when compiled on Android. */ -private val handlers: List = ServiceLoader.load( +private val handlers: List by lazy { + ServiceLoader.load( CoroutineExceptionHandler::class.java, CoroutineExceptionHandler::class.java.classLoader -).iterator().asSequence().toList() + ).iterator().asSequence().toList() +} internal actual fun initializeDefaultExceptionHandlers() { + /** + * For Android, we do not want to allow arbitrary disks read (service loader JAR scanning) + * as it causes ANR, so we are postponing service loading until the actual exception (crash in case of Android). + * For other applications it's not the issue to read the JAR, but it is the issue + * to read from disk/call service loader when e.g. OOM was thrown, as exception reporting will also throw, + * so we are initializing it eagerly. + * + * Alternatively, we can use our own FastServiceLoader (as for Dispatchers.Main) here as it gives x20 speedup, see + * https://github.com/Kotlin/kotlinx.coroutines/issues/878#issuecomment-445815632 + * but it doesn't seem worth the trouble. + */ + if (ANDROID_DETECTED) return // Load CEH and handlers CoroutineExceptionHandler + handlers } /**