Crash dans le développement mobile : ce que c'est, types et méthodes de prévention

Auteur : IT Sectr Publié le : 2026-03-29 Temps de lecture : 9 min

Crash est une terminaison anormale d'une application mobile due à une exception non traitée ou à une défaillance fatale du système. Selon Firebase Crashlytics, environ 2 % des utilisateurs subissent des crashes quotidiennement, et chaque plantage réduit la rétention de 10 à 20 %. Comprendre les causes et les méthodes de prévention des crashes est une compétence essentielle pour tout développeur mobile.

Points clés

  • Crash — une exception non traitée entraînant la terminaison anormale du processus
  • NullPointerException — le type de crash le plus courant dans les applications Java/Kotlin
  • Les crash reporters collectent la stack trace, l'état de l'appareil et les données utilisateur
  • Firebase Crashlytics — l'outil standard de surveillance des crashes dans le développement mobile
  • La prévention comprend une gestion appropriée des erreurs, des tests et la vérification de la null-sécurité

Qu'est-ce qu'un Crash

Crash est une terminaison anormale d'une application causée par une exception non traitée ou un signal fatal du système qui n'a pas été géré dans le code de l'application. Lorsque le système ou la machine virtuelle (JVM, ART) détecte une condition fatale — NullPointerException, IndexOutOfBoundsException, OutOfMemoryError — elle arrête immédiatement le processus et le décharge de la mémoire. L'utilisateur voit une fermeture soudaine de l'application sans aucune notification d'erreur système. Selon Google, les applications avec un taux sans crash inférieur à 99 % perdent jusqu'à 20 % de leurs utilisateurs actifs par mois.

Sur Android, le mécanisme de gestion des crashes diffère des systèmes de bureau. Au lieu d'une boîte de dialogue de débogage avec une stack trace, Android tue simplement le processus sans sauvegarder d'informations détaillées. La collecte d'informations sur les crashes est le travail de bibliothèques tierces (Crashlytics, Sentry, Bugsnag) qui interceptent les exceptions via Thread.setDefaultUncaughtExceptionHandler avant que le processus ne soit terminé.

iOS utilise un mécanisme similaire avec NSException et Mach exceptions pour gérer les erreurs fatales. Lorsqu'une exception non traitée se produit, le système termine l'application et le rapport est enregistré sous forme de fichier .crash. La collecte de crashes sur iOS nécessite une intégration avec Crashlytics ou le rapport intégré via Xcode Organizer.

Principaux types de crashes

Cinq catégories de crashes couvrent 90 % de toutes les défaillances dans les applications mobiles. Comprendre chaque type aide à diagnostiquer et corriger les problèmes en production plus rapidement.

NullPointerException — le roi des crashes

NullPointerException (NPE) est le type de crash le plus courant dans toutes les applications Java/Kotlin. Elle survient lors de la tentative d'appel d'une méthode ou d'accès à un champ d'un objet qui est null. Scénarios typiques : champ d'Activity non initialisé lors de la rotation de l'écran, réponse null du serveur lors de la désérialisation JSON, navigation négligente dans l'adaptateur RecyclerView.

Kotlin résout le problème des NPE au niveau du langage grâce aux types null-safe : String? ne peut pas être utilisé sans vérification explicite. Cependant, la compatibilité Java et la Réflexion créent toujours des risques. Utilisez les annotations @NonNull et @Nullable et activez strictNullChecks dans les outils d'analyse statique.

kotlin
fun safeLength(text: String?): Int {
    return text?.length ?: 0 // gestion sécurisée de null
}

IndexOutOfBoundsException et erreurs de collections

IndexOutOfBoundsException survient lors de l'accès à un index inexistant d'une liste ou d'un tableau. Scénarios courants : suppression d'un élément de RecyclerView sans synchronisation avec l'adaptateur, modification multi-thread d'ArrayList sans verrouillage, calcul incorrect de la position dans ViewPager. ConcurrentModificationException est un proche parent lors de l'itération et de la modification simultanées de collections.

Utilisez CopyOnWriteArrayList pour l'accès multi-thread ou les collections sans verrouillage de java.util.concurrent. Pour la synchronisation avec l'UI, utilisez DiffUtil qui calcule la différence entre les listes ancienne et nouvelle de manière sécurisée et efficace.

ClassCastException — problèmes de types

ClassCastException survient lors du casting d'un objet vers un type incompatible. Sous Android, les causes typiques sont : type de ViewHolder incorrect dans RecyclerView (différents types de cellules sans getItemViewType approprié), cast incorrect de Fragment lors de la navigation, objets Serializable avec différentes versions de classe.

Utilisez le safe-cast de Kotlin via l'opérateur as?, qui retourne null en cas d'incompatibilité de types. En Java — vérifiez avec instanceof avant le casting. Pour les objets Parcelable, déclarez toujours CREATOR dans chaque classe.

IllegalStateException et erreurs logiques

IllegalStateException signale l'appel d'une méthode dans un état inapproprié de l'objet. Un exemple typique sous Android — getSupportFragmentManager() après onSaveInstanceState, lorsque le commit() d'un fragment n'est pas autorisé. Un autre cas courant — appeler dismiss() sur une boîte de dialogue déjà fermée.

Vérifiez l'état du cycle de vie avant les opérations avec FragmentManager. Utilisez commitAllowingStateLoss() uniquement lorsque vous êtes sûr que la perte d'état n'est pas critique. En Kotlin, créez des constructeurs de type DSL qui éliminent les états invalides au niveau des types.

Native Crash (signaux SIGSEGV, SIGABRT)

Native Crash survient dans le code natif C/C++ en raison de violations de mémoire : déréférencement de pointeur nul, double-free, débordement de tampon de pile. Sous Android, ces crashes se produisent dans les bibliothèques NDK, les moteurs de jeu (Unity, Unreal) et les dépendances système. Native Crash N'est PAS intercepté par Thread.setDefaultUncaughtExceptionHandler — il tue le processus instantanément.

Pour diagnostiquer les crashes natifs, utilisez les fichiers minidump (Breakpad) ou les tombstones Android. Firebase Crashlytics prend en charge la collecte de crashes natifs via le NDK SDK. Sur iOS, un problème similaire est résolu avec PLCrashReporter.

Outils de crash reporting

Trois outils dominent le marché du crash reporting mobile. Chacun fournit la collecte de stack trace, l'agrégation par version d'application et les notifications de nouveaux crashes.

Firebase Crashlytics

Crashlytics est le crash reporter le plus populaire pour les applications mobiles, faisant partie de l'écosystème Firebase. Il collecte automatiquement les stack traces, les informations sur l'appareil, la version de l'OS et les clés personnalisées de l'utilisateur. L'intégration prend 10 minutes via la console Firebase et le plugin Gradle. Crashlytics prend également en charge les journaux en temps réel (Logcat) et les suivis utilisateur.

kotlin
FirebaseCrashlytics.getInstance()
    .setCustomKey("current_screen", "ProfileFragment")

FirebaseCrashlytics.getInstance()
    .log("User tapped login button")

Sentry

Sentry est une alternative à Crashlytics avec un système de filtrage plus flexible et la prise en charge de plus de 90 plateformes. Contrairement à Firebase, Sentry fournit un serveur auto-hébergé (self-hosted) pour les entreprises ayant des exigences strictes en matière de données. Sentry prend en charge le suivi distributif, les breadcrumbs et l'intégration avec les pipelines CI/CD.

Bugsnag et AppCenter

Bugsnag se distingue par la prise en charge d'alertes basées sur la sévérité : il classe les crashes en critical, error et warning. AppCenter de Microsoft est un outil gratuit avec des fonctionnalités de base pour les petits projets. Les deux prennent en charge Android, iOS, React Native et Flutter.

Comment analyser un crash

L'analyse d'un crash est le processus de reconstruction de l'image complète de ce qui s'est passé. La stack trace montre uniquement le dernier point de défaillance mais ne fournit pas le contexte qui a conduit au problème. Une approche professionnelle comprend quatre étapes.

La première étape — lire la stack trace. Identifiez la classe, la méthode et la ligne de code où l'exception s'est produite. Suivez la chaîne d'appels du cadre supérieur au cadre inférieur : la dernière ligne dans la pile est l'emplacement du crash, et les lignes supérieures sont la séquence d'appels. La désobfuscation (mapping ProGuard/R8) est obligatoire pour les builds de production.

La deuxième étape — le contexte de l'appareil. Crashlytics montre le modèle de l'appareil, la version de l'OS, la mémoire disponible et la version de l'application. Par exemple, un crash uniquement sur Samsung Galaxy S10 avec Android 11 indique un problème avec une version spécifique de One UI, et non une erreur de code générale.

La troisième étape — la reproduction sur un appareil de test. Si le crash ne se reproduit pas de manière stable, demandez à l'utilisateur les étapes exactes ou utilisez Remote Config pour journaliser avant la section de code problématique. Le test AB du correctif sur une partie de l'audience aide à confirmer la solution.

La quatrième étape — la surveillance post-correctif. Après la publication du correctif, surveillez le taux de crash pendant 3 à 5 jours. Si le crash disparaît complètement — le correctif a fonctionné. Si la fréquence a diminué mais n'est pas tombée à zéro — il existe un deuxième scénario nécessitant une analyse séparée.

Pratiques de prévention des crashes

Une approche systématique de la prévention des crashes comprend des outils d'analyse statique, des tests obligatoires de cas limites et une gestion appropriée des erreurs à tous les niveaux de l'application.

Analyse statique de code

Detekt (Kotlin) et Lint (Android) trouvent des problèmes potentiels au moment de la compilation : variables inutilisées, NPE potentiels, utilisation incorrecte de l'API. Incluez ces outils dans le pipeline CI avec un seuil d'erreurs. Par exemple, Detekt avec une configuration de 30+ avertissements ou tout blocage d'erreur ne laisse pas passer la compilation.

Tests unitaires et tests d'UI

La couverture des scénarios d'utilisation clés avec des tests unitaires est la protection de base contre les crashes de régression. Testez les modèles de données, ViewModel et les couches UseCase avec des cas limites : valeurs null, listes vides, JSON invalide. Les tests d'UI via Espresso ou Compose Test couvrent les flux critiques : authentification, paiement, onboarding.

Dégradation gracieuse

Concevez l'application de sorte qu'une défaillance dans un module ne fasse pas planter tout l'écran. Utilisez des blocs catch au niveau ViewModel avec un état de repli : afficher un espace réservé au lieu d'une liste, des données en cache en l'absence de réseau, une image de secours en cas d'erreur de chargement. Cela transforme un crash potentiel en un scénario UX contrôlé.

Déploiement progressif avec surveillance

Les déploiements progressifs sont une pratique standard sur Google Play et l'App Store : une nouvelle version est distribuée à 5 %, puis 20 %, puis 100 % de l'audience avec des intervalles de 1 à 3 jours. À chaque étape, le taux de crash est surveillé : si le taux sans crash tombe en dessous de 99,5 %, le déploiement s'arrête automatiquement. Firebase Remote Config permet de désactiver des fonctionnalités problématiques sans publier une nouvelle version.

Contrôle de version des dépendances

Renovate ou Dependabot dans le CI vérifient automatiquement les bibliothèques pour les vulnérabilités connues et les bogues critiques. La mise à jour d'une seule dépendance peut éliminer toute une classe de crashes. Cependant, testez les mises à jour sur l'environnement de staging avant de les déployer en production — une nouvelle version de bibliothèque peut contenir des changements incompatibles.

Foire aux questions

Peut-on prévenir 100 % des crashes ?

Non. Certains crashes sont causés par des facteurs indépendants de la volonté du développeur : erreurs système, problèmes matériels, incompatibilité du firmware. L'objectif est de réduire le taux à 0,1 % ou moins et de minimiser le temps de réponse pour les crashes restants.

En quoi un crash reporter diffère-t-il de l'analytique ?

Un crash reporter collecte la stack trace, l'état de la mémoire et les informations de l'appareil au moment du crash. L'analytique collecte les données comportementales de l'utilisateur. Crashlytics combine les deux approches, fournissant le contexte du crash ainsi que les clés personnalisées de l'utilisateur.

Pourquoi la stack trace est-elle obfusquée ?

ProGuard et R8 obfusquent le code pour protéger la propriété intellectuelle. Pour la désobfuscation, téléchargez le fichier de mapping dans Crashlytics lors de la publication. Sans fichier de mapping, la stack trace affichera a.a(), b.b() au lieu des vrais noms de classes et de méthodes.

Comment un crash reporter intercepte-t-il les exceptions ?

Via Thread.setDefaultUncaughtExceptionHandler sur Android : la bibliothèque enregistre son propre gestionnaire, qui reçoit l'exception non traitée en premier, sauvegarde les données, et ensuite seulement termine le processus. Sur iOS, NSSetUncaughtExceptionHandler est utilisé pour NSException et Mach exception handler pour les signaux.

Que sont les crashes fatals et non fatals ?

Fatal — l'application s'est terminée. Non fatal (exception attrapée) — le développeur a attrapé l'exception via try-catch, mais cela peut indiquer un problème potentiel. Crashlytics distingue ces types et permet de filtrer les non fatals séparément pour ne pas encombrer le tableau de bord.

Résumé

  • Crash — terminaison anormale de l'application due à une exception non traitée ou à un signal fatal
  • NullPointerException reste le type de crash le plus courant dans les applications mobiles
  • Firebase Crashlytics — l'outil standard pour collecter et analyser les crashes en production
  • L'analyse de crash comprend la lecture de la stack trace, le contexte de l'appareil et la reproduction dans un environnement de test
  • L'analyse statique (Detekt, Lint) prévient certains crashes au moment de la compilation
  • La dégradation gracieuse transforme les crashes potentiels en scénarios gérables avec des données de repli
  • Les fichiers de mapping sont obligatoires pour désobfusquer les stack traces dans les builds de 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