Global Exception Handler: essência, princípio de funcionamento e implementação em projetos

Autor: IT Sectr Publicado: 2026-05-27 Tempo de leitura: 8 min

Global Exception Handler — um mecanismo centralizado para capturar exceções não tratadas que evita o encerramento abrupto de aplicativos móveis. De acordo com Apple Developer, 2024, o tratamento adequado de exceções reduz a quantidade de falhas em 40–60% e melhora a experiência do usuário. Sem esse manipulador, qualquer exceção não tratada em uma thread em segundo plano leva ao fechamento imediato do aplicativo.

Pontos Principais

  • Global Exception Handler — um ponto central de coleta de todas as exceções não tratadas no aplicativo, prevenindo falhas
  • iOS NSSetUncaughtExceptionHandler — uma função C para interceptar exceções Objective-C na plataforma Apple
  • Android Thread.setDefaultUncaughtExceptionHandler — um mecanismo integrado da plataforma para captura global de exceções
  • Registro antes do encerramento — a principal tarefa do manipulador: salvar informações sobre a falha antes do processo terminar
  • Degradação gradual — o manipulador permite mostrar ao usuário uma tela de erro adequada em vez de um fechamento abrupto

O que é um Global Exception Handler?

Global Exception Handler — é um mecanismo centralizado para capturar exceções que não foram tratadas no nível de funções ou módulos individuais do aplicativo. No contexto do desenvolvimento móvel, esse manipulador atua como a última linha de defesa antes do encerramento anormal do processo.

iOS e Android fornecem APIs integradas para definir um manipulador global. A Apple usa NSSetUncaughtExceptionHandler para o ambiente Objective-C, enquanto o Google oferece Thread.setDefaultUncaughtExceptionHandler em Java/Kotlin. Ambos os mecanismos capturam exceções que não foram pegas por construções try-catch em todas as threads do aplicativo.

De acordo com o Crashlytics (Google, 2024), cerca de 25% das falhas ocorrem devido a exceções não tratadas em threads em segundo plano — uma área onde o Global Exception Handler é especialmente crítico. Os desenvolvedores geralmente se concentram na thread de UI, esquecendo das operações assíncronas.

Usar um manipulador global não substitui o tratamento local de erros, mas o complementa. A principal tarefa é salvar o máximo de informações sobre o estado do aplicativo no momento da exceção e encerrar corretamente.

Como funciona um manipulador global de exceções

O mecanismo de funcionamento do Global Exception Handler é baseado na interceptação de sinais do sistema operacional ou exceções em tempo de execução. Quando o código lança uma exceção que não é capturada por nenhum bloco try-catch, o controle é transferido para um manipulador previamente registrado.

No iOS, o manipulador é registrado via NSSetUncaughtExceptionHandler e recebe um objeto NSException com um stack trace completo. No Android, usa-se Thread.setDefaultUncaughtExceptionHandler, que aceita Thread e Throwable — fornecendo acesso ao tipo de exceção, mensagem e pilha de chamadas.

Após receber os dados da falha, o manipulador executa três ações obrigatórias: gravar um log no armazenamento local, enviar um relatório para o Crashlytics ou Sentry e encerrar o aplicativo corretamente. De acordo com a Apple WWDC 2023, o tempo de execução do manipulador é limitado a 5 segundos — após isso, o sistema encerra o processo à força.

Para aplicativos Swift a partir do iOS 13, foi introduzida a Signals API, que lida não apenas com exceções, mas também com sinais do sistema operacional — SIGABRT, SIGSEGV e SIGBUS, estendendo a cobertura do manipulador para erros de memória de baixo nível.

Implementação do Global Exception Handler no iOS

A implementação de um manipulador global no iOS requer a configuração de uma função C via NSSetUncaughtExceptionHandler. O manipulador é chamado de forma síncrona no momento de uma exceção não tratada e recebe o contexto completo do erro.

objective-c
void handleUncaughtException(NSException exception) {
    NSDictionary userInfo = [exception userInfo];
    NSArray stackTrace = [exception callStackSymbols];
    NSString reason = [exception reason];

    // Salvar log de crash em arquivo local
    NSString logPath = [NSSearchPathForDirectoriesInDomains(
        NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    [exceptionLog writeToFile:logPath atomically:YES];
}

int main(int argc, char argv[]) {
    NSSetUncaughtExceptionHandler(&handleUncaughtException);
    return UIApplicationMain(argc, argv, nil, nil);
}

Uma característica importante da implementação no iOS: o manipulador captura apenas exceções Objective-C. Erros Swift que usam o mecanismo throw-catch não chegam a este manipulador — eles exigem tratamento separado via Swift Error Handling. A partir do iOS 14, a Apple recomenda combinar NSSetUncaughtExceptionHandler com a Signals API para máxima cobertura.

De acordo com Apple Technical Note TN2151, após a chamada do manipulador, o aplicativo deve encerrar em 5 segundos. Qualquer tentativa de continuar a execução após retornar do manipulador leva a comportamento indefinido e uma nova falha.

Implementação do Global Exception Handler no Android

O Android fornece um mecanismo mais flexível para tratamento global de exceções via Thread.setDefaultUncaughtExceptionHandler. O manipulador recebe uma referência à thread onde ocorreu a exceção e o próprio objeto Throwable.

kotlin
class GlobalExceptionHandler : Thread.UncaughtExceptionHandler {

    override fun uncaughtException(thread: Thread, throwable: Throwable) {
        // Salvar log de crash em arquivo
        val stackTrace = throwable.stackTraceToString()
        val crashLog = "CRASH: ${thread.name}\n${stackTrace}"

        val file = File(context.cacheDir, "crash_log.txt")
        file.writeText(crashLog)

        // Enviar para Crashlytics
        FirebaseCrashlytics.getInstance()
            .recordException(throwable)

        // Encerrar processo
        android.os.Process.killProcess(
            android.os.Process.myPid()
        )
    }
}

// Configuração no Application.onCreate
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Thread.setDefaultUncaughtExceptionHandler(
            GlobalExceptionHandler()
        )
    }
}

Uma diferença chave da implementação no Android: cada thread tem seu próprio manipulador, e setDefaultUncaughtExceptionHandler define o manipulador para todas as threads que não têm um manipulador individual atribuído. Isso garante cobertura global — da thread de UI às AsyncTask em segundo plano e corrotinas.

No Android 12+, há uma limitação: após chamar uncaughtException, o aplicativo deve encerrar em 100 milissegundos. Se o manipulador realizar operações demoradas, o sistema pode matar o processo antes que o log seja gravado. Recomenda-se usar um serviço em segundo plano para enviar relatórios de falha.

Melhores práticas com Global Exception Handler

A primeira regra — não tente restaurar a operação do aplicativo após uma exceção não tratada. O estado do aplicativo após uma falha é indefinido, e continuar a execução pode levar à corrupção dos dados do usuário.

Minimizar o tempo de execução do manipulador

Limite de tempo — a principal restrição técnica do Global Exception Handler. No iOS é de 5 segundos, no Android — 100 milissegundos. Dentro do manipulador, apenas um conjunto mínimo de dados deve ser salvo: tipo de exceção, pilha de chamadas e o estado de algumas variáveis-chave.

O envio de solicitações de rede, gravação em banco de dados e serialização complexa devem ser adiados para um mecanismo diferido — por exemplo, salvar o log em um arquivo e enviá-lo na próxima inicialização do aplicativo.

Combinação com sistemas de relatório de falhas

Serviços de relatório de falhas — Firebase Crashlytics, Sentry, Bugsnag — definem seu próprio manipulador global. Se um desenvolvedor definir um manipulador personalizado adicional, ele precisa passar o controle para o sistema de relatório de falhas após suas próprias ações. No Android, usa-se composição de manipuladores: execute sua lógica e depois chame o manipulador anterior.

Para Firebase Crashlytics, é recomendado não definir um Thread.setDefaultUncaughtExceptionHandler personalizado — o SDK do Crashlytics faz isso automaticamente na inicialização.

Registro de informações adicionais

Contexto do usuário — além da pilha de chamadas padrão, é útil registrar a versão do aplicativo, versão do SO, tamanho da memória disponível e tempo de atividade antes da falha. Esses dados são criticamente importantes para reproduzir e corrigir o problema.

No iOS, pode-se usar NSSetUncaughtExceptionHandler não apenas para gravar, mas também para armazenamento temporário em NSUserDefaults com o sinalizador synchronize — isso garante a persistência mesmo no encerramento imediato do processo.

Teste do manipulador antes do lançamento

Teste obrigatório — o Global Exception Handler deve ser testado em cada etapa do CI/CD. No iOS, uma exceção de teste pode ser acionada via @throw NSException, no Android — via throw RuntimeException(). Verifique se o manipulador é chamado, o log é salvo e o aplicativo encerra corretamente.

De acordo com Google I/O 2023, mais de 30% das falhas em produção ocorrem em dispositivos que o desenvolvedor não testou — diferentes versões do Android, firmware personalizado, memória limitada.

Erros comuns ao usar o manipulador

O primeiro e mais comum erro — tentar continuar a execução do aplicativo após tratar uma exceção. Depois de chamar uncaughtException, o aplicativo está em um estado instável, e qualquer operação adicional pode causar erros em cascata e corrupção de dados.

O segundo erro — realizar operações demoradas dentro do manipulador. Solicitações de rede, gravação de arquivos grandes ou cálculos complexos não são concluídos antes do encerramento forçado do processo. De acordo com Apple Technical Q&A QA1468, tentar enviar uma solicitação HTTP dentro do manipulador é a principal causa de perda de relatórios de falha.

O terceiro erro — ignorar threads em segundo plano. Um Global Exception Handler definido apenas para a thread principal não protege contra falhas em corrotinas, DispatchQueue, AsyncTask ou RxJava. No Android, cada thread deve ter seu próprio manipulador — e setDefaultUncaughtExceptionHandler só resolve isso para threads sem um manipulador individual.

O quarto erro — falta de fallback para sinais do SO. NSSetUncaughtExceptionHandler no iOS não captura SIGABRT, SIGSEGV e SIGBUS. Esses sinais exigem configuração separada de manipuladores via sigaction API. Os desenvolvedores descobrem isso apenas quando o aplicativo falha sem um único relatório de falha.

O quinto erro — registro de dados confidenciais. O log de falha pode conter e-mails, tokens de autenticação ou dados pessoais dos usuários. Isso viola o GDPR e as Diretrizes de Revisão da App Store da Apple. Sempre filtre os dados transmitidos usando regex ou uma lista de campos permitidos.

Perguntas Frequentes

Pode-se restaurar o aplicativo após uma exceção global?

Não — após invocar um Global Exception Handler, o estado do aplicativo é indefinido. Qualquer tentativa de continuar a execução pode levar à corrupção de dados. A única ação correta é salvar o log da falha e encerrar o processo.

O Global Exception Handler captura todos os tipos de erros?

Nem todos — no iOS, NSSetUncaughtExceptionHandler captura apenas exceções Objective-C. Erros Swift e sinais do SO (SIGSEGV, SIGABRT) exigem manipuladores separados. No Android, Thread.setDefaultUncaughtExceptionHandler captura todas as RuntimeExceptions, mas não erros de código nativo via JNI.

Como passar o controle para um sistema de relatório de falhas após meu manipulador?

Salve uma referência ao manipulador anterior via Thread.getDefaultUncaughtExceptionHandler() antes de definir o seu. No final do seu manipulador, chame previousHandler.uncaughtException(thread, throwable) — isso garante que o Crashlytics ou Sentry recebam seus dados.

O que fazer se a falha ocorrer em código nativo C/C++?

Para código nativo, é necessário tratamento de sinais via sigaction() — SIGSEGV, SIGABRT, SIGBUS. No Android, pode-se usar Google Breakpad ou Crashpad. No iOS a partir da versão 13, a Signals API está disponível para lidar com exceções mach.

O Global Exception Handler pode afetar o desempenho?

Não — definir o manipulador afeta apenas o momento em que uma exceção ocorre. Na operação normal do aplicativo, não há overhead. O único risco é um vazamento de memória se o manipulador mantiver uma referência a uma Activity ou Context, impedindo a coleta de lixo.

Resumo

  • Global Exception Handler — a última linha de defesa antes de uma falha, obrigatório em qualquer aplicativo de produção
  • iOS NSSetUncaughtExceptionHandler captura exceções Objective-C com limite de processamento de 5 segundos
  • Android Thread.setDefaultUncaughtExceptionHandler funciona para todas as threads sem manipulador pessoal
  • Tempo de execução do manipulador deve ser mínimo — salvar dados e encerrar o processo sem tentar recuperação
  • Sinais do SO (SIGSEGV, SIGABRT) não são capturados por manipuladores padrão — é necessário sigaction API
  • Sistemas de relatório de falhas devem ser chamados via composição de manipuladores, passando o controle após sua lógica
  • Teste do manipulador em CI/CD — etapa obrigatória para evitar perda de relatórios de falha em produção

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também