Global Exception Handler : essence, principe de fonctionnement et implémentation dans les projets

Auteur : IT Sectr Publié le : 2026-05-27 Temps de lecture : 8 min

Global Exception Handler — un mécanisme centralisé pour intercepter les exceptions non traitées, empêchant l'arrêt brutal des applications mobiles. Selon Apple Developer, 2024, un traitement correct des exceptions réduit le nombre de crashs de 40–60% et améliore l'expérience utilisateur. Sans un tel gestionnaire, toute exception non traitée dans un thread d'arrière-plan entraîne la fermeture immédiate de l'application.

Points Clés

  • Global Exception Handler — un point de collecte central pour toutes les exceptions non traitées dans l'application, empêchant les crashs
  • iOS NSSetUncaughtExceptionHandler — une fonction C pour intercepter les exceptions Objective-C sur la plateforme Apple
  • Android Thread.setDefaultUncaughtExceptionHandler — un mécanisme intégré de la plateforme pour l'interception globale des exceptions
  • Journalisation avant la fermeture — la tâche principale du gestionnaire : sauvegarder les informations de crash avant la fin du processus
  • Dégradation progressive — le gestionnaire permet d'afficher un écran d'erreur approprié à l'utilisateur au lieu d'un arrêt brutal

Qu'est-ce qu'un Global Exception Handler ?

Global Exception Handler — est un mécanisme centralisé pour intercepter les exceptions qui n'ont pas été traitées au niveau des fonctions ou modules individuels de l'application. Dans le contexte du développement mobile, un tel gestionnaire agit comme la dernière ligne de défense avant l'arrêt anormal du processus.

iOS et Android fournissent des API intégrées pour définir un gestionnaire global. Apple utilise NSSetUncaughtExceptionHandler pour l'environnement Objective-C, tandis que Google propose Thread.setDefaultUncaughtExceptionHandler en Java/Kotlin. Les deux mécanismes interceptent les exceptions qui n'ont pas été capturées par les constructions try-catch sur tous les threads de l'application.

Selon Crashlytics (Google, 2024), environ 25 % des crashs sont dus à des exceptions non traitées dans les threads d'arrière-plan — un domaine où le Global Exception Handler est particulièrement critique. Les développeurs se concentrent souvent sur le thread UI, oubliant les opérations asynchrones.

L'utilisation d'un gestionnaire global ne remplace pas la gestion locale des erreurs, mais la complète. La tâche principale est de sauvegarder un maximum d'informations sur l'état de l'application au moment de l'exception et de se terminer correctement.

Comment fonctionne un gestionnaire global d'exceptions

Le mécanisme de fonctionnement du Global Exception Handler est basé sur l'interception de signaux du système d'exploitation ou d'exceptions d'exécution. Lorsque le code lève une exception qui n'est capturée par aucun bloc try-catch, le contrôle est transféré à un gestionnaire préenregistré.

Sur iOS, le gestionnaire est enregistré via NSSetUncaughtExceptionHandler et reçoit un objet NSException avec une pile d'appels complète. Sur Android, on utilise Thread.setDefaultUncaughtExceptionHandler, qui accepte Thread et Throwable — fournissant l'accès au type d'exception, au message et à la pile d'appels.

Après avoir reçu les données de crash, le gestionnaire effectue trois actions obligatoires : écrire un journal dans le stockage local, envoyer un rapport à Crashlytics ou Sentry, et terminer l'application correctement. Selon l'Apple WWDC 2023, le temps d'exécution du gestionnaire est limité à 5 secondes — après quoi le système termine le processus de force.

Pour les applications Swift à partir d'iOS 13, la Signals API a été introduite, qui gère non seulement les exceptions mais aussi les signaux du système d'exploitation — SIGABRT, SIGSEGV et SIGBUS, étendant la couverture du gestionnaire aux erreurs mémoire de bas niveau.

Implémentation du Global Exception Handler sur iOS

L'implémentation d'un gestionnaire global sur iOS nécessite de définir une fonction C via NSSetUncaughtExceptionHandler. Le gestionnaire est appelé de manière synchrone au moment d'une exception non traitée et reçoit le contexte complet de l'erreur.

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

    // Enregistrer le journal de crash dans un fichier 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);
}

Une caractéristique importante de l'implémentation iOS : le gestionnaire ne capture que les exceptions Objective-C. Les erreurs Swift utilisant le mécanisme throw-catch n'atteignent pas ce gestionnaire — elles nécessitent un traitement séparé via Swift Error Handling. À partir d'iOS 14, Apple recommande de combiner NSSetUncaughtExceptionHandler avec la Signals API pour une couverture maximale.

Selon Apple Technical Note TN2151, après l'appel du gestionnaire, l'application doit se terminer dans les 5 secondes. Toute tentative de continuer l'exécution après le retour du gestionnaire entraîne un comportement indéfini et un nouveau crash.

Implémentation du Global Exception Handler sur Android

Android fournit un mécanisme plus flexible pour la gestion globale des exceptions via Thread.setDefaultUncaughtExceptionHandler. Le gestionnaire reçoit une référence au thread où l'exception s'est produite et l'objet Throwable lui-même.

kotlin
class GlobalExceptionHandler : Thread.UncaughtExceptionHandler {

    override fun uncaughtException(thread: Thread, throwable: Throwable) {
        // Enregistrer le journal de crash dans un fichier
        val stackTrace = throwable.stackTraceToString()
        val crashLog = "CRASH: ${thread.name}\n${stackTrace}"

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

        // Envoyer à Crashlytics
        FirebaseCrashlytics.getInstance()
            .recordException(throwable)

        // Terminer le processus
        android.os.Process.killProcess(
            android.os.Process.myPid()
        )
    }
}

// Configuration dans Application.onCreate
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Thread.setDefaultUncaughtExceptionHandler(
            GlobalExceptionHandler()
        )
    }
}

Une différence clé de l'implémentation Android : chaque thread a son propre gestionnaire, et setDefaultUncaughtExceptionHandler définit le gestionnaire pour tous les threads qui n'ont pas de gestionnaire individuel attribué. Cela garantit une couverture globale — du thread UI aux AsyncTask d'arrière-plan et coroutines.

Sur Android 12+, il y a une limitation : après avoir appelé uncaughtException, l'application doit se terminer dans les 100 millisecondes. Si le gestionnaire effectue des opérations longues, le système peut tuer le processus avant que le journal ne soit écrit. Il est recommandé d'utiliser un service d'arrière-plan pour envoyer les rapports de crash.

Bonnes pratiques avec Global Exception Handler

La première règle — ne tentez pas de restaurer le fonctionnement de l'application après une exception non traitée. L'état de l'application après un crash est indéfini, et continuer l'exécution peut entraîner la corruption des données utilisateur.

Minimiser le temps d'exécution du gestionnaire

Limite de temps — la principale contrainte technique du Global Exception Handler. Sur iOS, elle est de 5 secondes, sur Android — 100 millisecondes. À l'intérieur du gestionnaire, seul un ensemble minimal de données doit être sauvegardé : type d'exception, pile d'appels et état de quelques variables clés.

L'envoi de requêtes réseau, l'écriture dans la base de données et la sérialisation complexe doivent être différés vers un mécanisme différé — par exemple, sauvegarder le journal dans un fichier et l'envoyer au prochain lancement de l'application.

Combinaison avec les systèmes de signalement de crash

Services de signalement de crash — Firebase Crashlytics, Sentry, Bugsnag — définissent leur propre gestionnaire global. Si un développeur définit un gestionnaire personnalisé supplémentaire, il doit passer le contrôle au système de signalement de crash après ses propres actions. Sur Android, on utilise la composition de gestionnaires : exécuter votre logique, puis appeler le gestionnaire précédent.

Pour Firebase Crashlytics, il est recommandé de ne pas définir de Thread.setDefaultUncaughtExceptionHandler personnalisé — le SDK Crashlytics le fait automatiquement à l'initialisation.

Journalisation d'informations supplémentaires

Contexte utilisateur — en plus de la pile d'appels standard, il est utile de journaliser la version de l'application, la version de l'OS, la taille de la mémoire disponible et le temps de fonctionnement avant le crash. Ces données sont cruciales pour reproduire et résoudre le problème.

Sur iOS, on peut utiliser NSSetUncaughtExceptionHandler non seulement pour écrire, mais aussi pour le stockage temporaire dans NSUserDefaults avec le drapeau synchronize — cela garantit la persistance même en cas d'arrêt immédiat du processus.

Test du gestionnaire avant la publication

Test obligatoire — le Global Exception Handler doit être testé à chaque étape du CI/CD. Sur iOS, une exception de test peut être déclenchée via @throw NSException, sur Android — via throw RuntimeException(). Vérifiez que le gestionnaire est appelé, que le journal est sauvegardé et que l'application se termine correctement.

Selon Google I/O 2023, plus de 30 % des crashs en production se produisent sur des appareils que le développeur n'a pas testés — différentes versions d'Android, firmware personnalisé, mémoire limitée.

Erreurs courantes lors de l'utilisation du gestionnaire

La première erreur et la plus courante — tenter de continuer l'exécution de l'application après avoir traité une exception. Après avoir appelé uncaughtException, l'application est dans un état instable, et toute opération supplémentaire peut provoquer des erreurs en cascade et une corruption des données.

La deuxième erreur — effectuer des opérations longues à l'intérieur du gestionnaire. Les requêtes réseau, l'écriture de fichiers volumineux ou les calculs complexes ne se terminent pas avant l'arrêt forcé du processus. Selon Apple Technical Q&A QA1468, tenter d'envoyer une requête HTTP à l'intérieur du gestionnaire est la principale cause de perte de rapports de crash.

La troisième erreur — ignorer les threads d'arrière-plan. Un Global Exception Handler défini uniquement pour le thread principal ne protège pas contre les crashs dans les coroutines, DispatchQueue, AsyncTask ou RxJava. Sur Android, chaque thread doit avoir son propre gestionnaire — et setDefaultUncaughtExceptionHandler ne résout cela que pour les threads sans gestionnaire individuel.

La quatrième erreur — absence de repli pour les signaux de l'OS. NSSetUncaughtExceptionHandler sur iOS ne capture pas SIGABRT, SIGSEGV et SIGBUS. Ces signaux nécessitent une configuration séparée de gestionnaires via l'API sigaction. Les développeurs ne le découvrent que lorsque l'application plante sans aucun rapport de crash.

La cinquième erreur — journalisation de données confidentielles. Le journal de crash peut contenir des e-mails, des jetons d'authentification ou des données personnelles des utilisateurs. Cela viole le RGPD et les Directives d'examen de l'App Store d'Apple. Filtrez toujours les données transmises à l'aide d'expressions régulières ou d'une liste blanche de champs autorisés.

Foire aux questions

Peut-on restaurer l'application après une exception globale ?

Non — après l'invocation d'un Global Exception Handler, l'état de l'application est indéfini. Toute tentative de continuer l'exécution peut entraîner une corruption des données. La seule action correcte est de sauvegarder le journal de crash et de terminer le processus.

Le Global Exception Handler capture-t-il tous les types d'erreurs ?

Pas tous — sur iOS, NSSetUncaughtExceptionHandler ne capture que les exceptions Objective-C. Les erreurs Swift et les signaux de l'OS (SIGSEGV, SIGABRT) nécessitent des gestionnaires séparés. Sur Android, Thread.setDefaultUncaughtExceptionHandler capture toutes les RuntimeExceptions mais pas les erreurs de code natif via JNI.

Comment passer le contrôle à un système de signalement de crash après mon gestionnaire ?

Sauvegardez une référence au gestionnaire précédent via Thread.getDefaultUncaughtExceptionHandler() avant de définir le vôtre. À la fin de votre gestionnaire, appelez previousHandler.uncaughtException(thread, throwable) — cela garantit que Crashlytics ou Sentry reçoivent leurs données.

Que faire si un crash se produit dans du code natif C/C++ ?

Pour le code natif, un traitement des signaux via sigaction() est nécessaire — SIGSEGV, SIGABRT, SIGBUS. Sur Android, vous pouvez utiliser Google Breakpad ou Crashpad. Sur iOS à partir de la version 13, la Signals API est disponible pour gérer les exceptions mach.

Le Global Exception Handler peut-il affecter les performances ?

Non — la définition du gestionnaire n'affecte que le moment où une exception se produit. En fonctionnement normal de l'application, il n'y a pas de surcharge. Le seul risque est une fuite mémoire si le gestionnaire conserve une référence à une Activity ou un Context, empêchant le ramasse-miettes.

Résumé

  • Global Exception Handler — la dernière ligne de défense avant un crash, obligatoire dans toute application de production
  • iOS NSSetUncaughtExceptionHandler capture les exceptions Objective-C avec une limite de traitement de 5 secondes
  • Android Thread.setDefaultUncaughtExceptionHandler fonctionne pour tous les threads sans gestionnaire personnel
  • Temps d'exécution du gestionnaire minimal — sauvegarder les données et terminer le processus sans tenter de récupération
  • Signaux de l'OS (SIGSEGV, SIGABRT) ne sont pas capturés par les gestionnaires standard — API sigaction requise
  • Systèmes de signalement de crash doivent être appelés via composition de gestionnaires, en passant le contrôle après votre logique
  • Test du gestionnaire dans le CI/CD — étape obligatoire pour éviter la perte de rapports de crash en production

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi