CoroutineExceptionHandler : gestionnaire global des exceptions non interceptées
Installez un CoroutineExceptionHandler pour journaliser les exceptions non gérées ou permettre leur récupération.
CoroutineExceptionHandler : gestionnaire global des exceptions non interceptées est une leçon Kotlin Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Kotlin Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Kotlin Academy comprend 4 leçons au total.
Qu'est-ce que CoroutineExceptionHandler ?
CoroutineExceptionHandler est un élément de contexte qui gère les exceptions non interceptées des coroutines ne disposant pas de gestionnaire de capture. Il sert de dernier recours.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { context, exception ->
println("Caught unhandled: ${exception.message}")
}
fun main() = runBlocking {
val scope = CoroutineScope(Dispatchers.Default + handler)
scope.launch { throw RuntimeException("oops") }
delay(100)
}Uniquement pour les coroutines racines
CoroutineExceptionHandler intercepte uniquement les exceptions des coroutines racines (lancées directement dans une portée). Les coroutines enfants se propagent jusqu'à leur parent, et non jusqu'au gestionnaire.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
// Root coroutine — handler fires:
CoroutineScope(handler).launch {
throw RuntimeException("root error")
}
delay(100)
// NOT handler (child of coroutineScope):
// launch { launch { throw RuntimeException() } }
}L'exception n'est pas supprimée
Le gestionnaire est appelé après que l'exception a déjà annulé la coroutine. Il sert à la journalisation, au signalement des plantages ou au nettoyage, et non à reprendre l'exécution.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e ->
println("[CrashReport] ${e::class.simpleName}: ${e.message}")
// send to Crashlytics, Sentry, etc.
}
fun main() = runBlocking {
CoroutineScope(SupervisorJob() + handler).apply {
launch { throw IllegalStateException("state error") }
launch { delay(100); println("still alive") }
delay(200)
cancel()
}
}Gestionnaire et SupervisorJob
La combinaison SupervisorJob + CoroutineExceptionHandler est le modèle standard pour les portées de longue durée : les enfants échouent indépendamment et les échecs non gérés sont journalisés.
import kotlinx.coroutines.*
class AppScope {
private val handler = CoroutineExceptionHandler { _, e ->
println("Uncaught: ${e.message}")
}
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
}
fun main() = runBlocking {
val app = AppScope()
app.scope.launch { throw RuntimeException("task failed") }
app.scope.launch { delay(100); println("other task ok") }
delay(200)
app.scope.cancel()
}Gestionnaire avec des opérations asynchrones
Avec async, les exceptions sont stockées dans le Deferred et levées lors de l'appel à await(). Le gestionnaire ne se déclenche NOT pas pour async, sauf si le différé n'est pas attendu.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob() + handler)
val deferred = scope.async { throw RuntimeException("async error") }
try {
deferred.await() // exception thrown here
} catch (e: RuntimeException) {
println("Caught from await: ${e.message}")
}
delay(50)
scope.cancel()
}Comparaison avec Thread.UncaughtExceptionHandler
Contrairement à UncaughtExceptionHandler de Java, le gestionnaire de Kotlin fait partie du contexte de la coroutine et s'applique uniquement aux coroutines de cette portée.
import kotlinx.coroutines.*
// Java style (applies to threads):
Thread.setDefaultUncaughtExceptionHandler { t, e ->
println("Thread ${t.name} threw: ${e.message}")
}
// Kotlin coroutine style (applies to coroutines in scope):
val handler = CoroutineExceptionHandler { _, e ->
println("Coroutine threw: ${e.message}")
}
fun main() = runBlocking { println("Handlers target different concurrency models") }Modèle de journalisation avec MDC
Dans les applications serveur, le gestionnaire peut récupérer les informations du contexte de la coroutine, comme les identifiants de requête, pour effectuer une journalisation structurée avant de les transmettre au cadre de journalisation.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { ctx, e ->
val jobName = ctx[CoroutineName]?.name ?: "unknown"
println("[${jobName}] ERROR: ${e.message}")
}
fun main() = runBlocking {
CoroutineScope(SupervisorJob() + handler).launch(CoroutineName("DataLoader")) {
throw RuntimeException("fetch failed")
}
delay(100)
}Intégration du signalement des plantages
Utilisez le gestionnaire pour transmettre les exceptions non interceptées à des services de signalement des plantages tels que Firebase Crashlytics ou Sentry.
import kotlinx.coroutines.*
object CrashReporter {
fun record(e: Throwable) = println("[Crashlytics] ${e.message}")
}
val handler = CoroutineExceptionHandler { _, e ->
if (e !is CancellationException) CrashReporter.record(e)
}
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
fun main() = runBlocking {
appScope.launch { throw RuntimeException("unhandled in production") }
delay(100)
appScope.cancel()
}Héritage du gestionnaire
Le gestionnaire du contexte parent n'est NOT pas automatiquement hérité par les coroutines enfants. Il doit se trouver dans le contexte de la coroutine racine pour être déclenché.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
// Handler only fires at root level:
CoroutineScope(SupervisorJob() + handler).launch {
// Child of root — exception propagates to root handler:
launch { throw RuntimeException("nested") }
}
delay(100)
}Résumé des bonnes pratiques
Installez toujours un CoroutineExceptionHandler sur les portées de l'application ou des fonctionnalités. Journalisez toute exception qui n'est pas liée à l'annulation. Ne vous appuyez jamais dessus pour le contrôle du flux : il sert uniquement à l'observabilité.
import kotlinx.coroutines.*
val globalHandler = CoroutineExceptionHandler { ctx, e ->
if (e !is CancellationException) {
println("[ERROR] ${ctx[CoroutineName]?.name}: ${e.message}")
}
}
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + globalHandler)
fun main() = runBlocking {
appScope.launch(CoroutineName("Auth")) { throw RuntimeException("token expired") }
delay(100); appScope.cancel()
}Vérification rapide
Pour quel type de coroutine CoroutineExceptionHandler ne se déclenche-t-il NOT pas automatiquement ?
Récapitulatif
CoroutineExceptionHandler est un observateur de dernier recours pour les exceptions non interceptées dans les coroutines racines. Combinez-le avec SupervisorJob pour les portées de longue durée. Utilisez-le pour la journalisation et le signalement des plantages, jamais pour le contrôle du flux.
Questions Fréquemment Posées
La leçon « CoroutineExceptionHandler : gestionnaire global des exceptions non interceptées » est-elle gratuite ?
Oui — le texte complet de « CoroutineExceptionHandler : gestionnaire global des exceptions non interceptées » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Kotlin Academy, passe à CoddyKit PRO. Le cours Kotlin Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « CoroutineExceptionHandler : gestionnaire global des exceptions non interceptées » ?
Installez un CoroutineExceptionHandler pour journaliser les exceptions non gérées ou permettre leur récupération. Tu pratiques Kotlin Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Kotlin Academy ?
Aucune expérience préalable n'est requise. Kotlin Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « CoroutineExceptionHandler : gestionnaire global des exceptions non interceptées » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Kotlin Academy ?
Oui. Chaque leçon Kotlin Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- SupervisorJob ou Job : isolation des échecs
- CoroutineExceptionHandler : gestionnaire global des exceptions non interceptées
- Propagation des exceptions avec async/await
- Concevoir des architectures de coroutines résilientes