0Pricing
Kotlin Academy · Aula

CoroutineExceptionHandler: manipulador global de exceções não capturadas

Instale um CoroutineExceptionHandler para registrar ou recuperar-se de exceções não tratadas.

CoroutineExceptionHandler: manipulador global de exceções não capturadas é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.

O Que é CoroutineExceptionHandler

CoroutineExceptionHandler é um elemento de contexto que trata exceções não capturadas de corrotinas que não têm um manipulador de captura. Ele atua como último recurso.

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)
}

Somente para Corrotinas Raiz

CoroutineExceptionHandler captura exceções somente de corrotinas raiz (iniciadas diretamente em um escopo). As corrotinas filhas propagam as exceções para o pai, não para o manipulador.

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() } }
}

A Exceção Não é Suprimida

O manipulador é chamado depois que a exceção já cancelou a corrotina. Ele serve para registro, relatórios de falhas ou limpeza — não para retomar a execução.

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()
    }
}

Manipulador + SupervisorJob

A combinação de SupervisorJob + CoroutineExceptionHandler é o padrão para escopos de longa duração: os filhos falham de forma independente e as falhas não tratadas são registradas.

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()
}

Manipulador com Execução Assíncrona

Para async, as exceções são armazenadas em Deferred e lançadas em await(). O manipulador NÃO é acionado para async, a menos que o deferred não seja aguardado.

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()
}

Comparação com UncaughtExceptionHandler de Thread

Ao contrário do UncaughtExceptionHandler do Java, o manipulador do Kotlin faz parte do contexto da corrotina e só se aplica às corrotinas dentro desse escopo.

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") }

Padrão de Registro com MDC

Em aplicações de servidor, o manipulador pode capturar informações do contexto da corrotina (como IDs de requisição) para registro estruturado antes de encaminhá-las à estrutura de registro.

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)
}

Integração com Relatórios de Falhas

Use o manipulador para encaminhar exceções não capturadas a serviços de relatórios de falhas, como 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()
}

Herança do Manipulador

O manipulador do contexto pai NÃO é herdado automaticamente pelas corrotinas filhas. Ele precisa estar no contexto da corrotina raiz para ser acionado.

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)
}

Resumo das Boas Práticas

Instale sempre um CoroutineExceptionHandler nos escopos do nível da aplicação ou do recurso. Registre toda exceção que não seja de cancelamento. Nunca dependa dele para controlar o fluxo — ele serve apenas à observabilidade.

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()
}

Verificação Rápida

Para qual tipo de corrotina o CoroutineExceptionHandler NÃO é acionado automaticamente?

Recapitulação

CoroutineExceptionHandler é um observador de último recurso para exceções não capturadas em corrotinas raiz. Combine-o com SupervisorJob para escopos de longa duração. Use-o para registro e relatórios de falhas — nunca para controlar o fluxo.

Perguntas Frequentes

A aula “CoroutineExceptionHandler: manipulador global de exceções não capturadas” é grátis?

Sim — o texto completo de “CoroutineExceptionHandler: manipulador global de exceções não capturadas” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.

O que vou aprender em “CoroutineExceptionHandler: manipulador global de exceções não capturadas”?

Instale um CoroutineExceptionHandler para registrar ou recuperar-se de exceções não tratadas. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Kotlin Academy?

Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “CoroutineExceptionHandler: manipulador global de exceções não capturadas”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Kotlin Academy?

Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. SupervisorJob vs Job: isolamento de falhas
  2. CoroutineExceptionHandler: manipulador global de exceções não capturadas
  3. Propagação de exceções em async/await
  4. Projetando arquiteturas resilientes de corrotinas
← Voltar para Kotlin Academy