OutOfMemoryError dans le développement d'applications : qu'est-ce que c'est, causes et méthodes de prévention

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

OutOfMemoryError est une exception fatale qui se produit lorsque la machine virtuelle Java (JVM) ou Android Runtime (ART) ne peut pas allouer de mémoire pour un nouvel objet en raison du manque d'espace dans le Heap. Selon Square Engineering, 70 % des OutOfMemoryError dans les applications mobiles sont causés par des fuites de mémoire, et non par un dépassement réel de la limite. Comprendre les causes d'OOM est la clé de la stabilité de l'application.

Points Clés

  • OutOfMemoryError — une exception lorsque le Heap est insuffisant pour créer un nouvel objet
  • Heap — la zone mémoire où vivent tous les objets Java/Kotlin
  • Bitmap — le principal consommateur de Heap sous Android, une source typique d'OOM
  • Heap Dump — un instantané du Heap pour analyser qui occupe combien de mémoire
  • Traitement de l'OOM nécessite de corriger les fuites et d'optimiser la consommation mémoire

Qu'est-ce que OutOfMemoryError

OutOfMemoryError (OOM) est une exception de la famille VirtualMachineError en Java/Kotlin qui signale l'incapacité d'allouer de la mémoire pour un nouvel objet. Contrairement aux exceptions vérifiées, OOM est une Error et ne nécessite pas de traitement via catch — bien qu'il puisse techniquement être attrapé. Après la survenue d'un OOM, l'application est généralement dans un état instable et il est recommandé de la terminer.

Sous Android, chaque application a une limite de Heap définie par le fabricant de l'appareil. Pour les smartphones modernes avec 6+ Go de RAM, la limite est de 256 à 512 Mo, pour les appareils économiques — de 128 à 192 Mo. Lorsque le volume total de tous les objets vivants dépasse cette limite, ART lance OutOfMemoryError.

Il est important de comprendre : OOM ne signifie pas toujours que l'appareil n'a plus de mémoire physique. Cela signifie que l'application a épuisé sa limite de Heap définie par le système. D'autres applications peuvent avoir de la mémoire libre, mais votre application ne peut pas l'utiliser en raison de l'isolation des processus sous Android.

Causes principales de OutOfMemoryError

Cinq scénarios mènent régulièrement à OOM dans les applications mobiles. Chaque scénario est associé à un type de données ou une opération spécifique.

Bitmap Sans Redimensionnement

Bitmap est le principal consommateur de mémoire dans les applications Android. Charger une image FullHD (1920 × 1080) en taille originale occupe 8,3 Mo au format ARGB_8888. S'il y a 50 de ces images dans un RecyclerView, cela fait 415 Mo, dépassant le Heap de n'importe quel appareil. Charger des images sans inSampleSize garantit un OOM sur les appareils faibles.

Utilisez Glide ou Coil pour le redimensionnement automatique. Ces bibliothèques chargent les images dans une taille correspondant à la View, pas à la résolution d'origine. Pour une utilisation directe de BitmapFactory.Options, appliquez inSampleSize : calculez-le comme une puissance de deux pour que la taille finale ne dépasse pas 2048 × 2048 pixels. Utilisez également RGB_565 au lieu d'ARGB_8888 pour les images sans transparence — cela réduit de moitié la consommation mémoire.

kotlin
fun loadScaledBitmap(path: String, reqWidth: Int): Bitmap? {
    val opts = BitmapFactory.Options().apply {
        inJustDecodeBounds = true
    }
    BitmapFactory.decodeFile(path, opts)
    opts.inSampleSize = calculateSampleSize(opts.outWidth, reqWidth)
    opts.inJustDecodeBounds = false
    return BitmapFactory.decodeFile(path, opts)
}

Fuites Mémoire (Accumulation)

Une seule fuite de quelques Ko ne provoquera pas d'OOM. Mais des dizaines de fuites sur chaque écran s'accumulent : chaque transition d'écran ajoute une fuite, le GC ne peut pas libérer les objets et le Heap se remplit. Un schéma typique : l'utilisateur ouvre et ferme l'écran de profil 20 fois → le Heap augmente de 200 Mo → l'application plante avec OOM.

Installez LeakCanary dans le projet pour la détection automatique des fuites. Il montrera chaque objet fuyard avec une trace de pile exacte. Après avoir corrigé toutes les fuites, la consommation du Heap devient stable : après la fermeture d'un écran, la mémoire revient au niveau de base.

Fichiers Volumineux en Mémoire

Charger des fichiers entiers en byte[] est un chemin direct vers OOM. Un fichier JSON de 50 Mo lors de l'analyse créera une chaîne de la même taille plus un modèle DOM. Les fichiers vidéo chargés en mémoire, les tampons audio et les grands ensembles de données protobuf — tous peuvent dépasser la limite de Heap en une seule opération.

Traitez les données volumineuses avec des flux : InputStream avec un tampon de 4 à 8 Ko, analyseur JSON en streaming (Jackson ou Gson avec JsonReader), MediaCodec pour la vidéo. N'appelez jamais File.readBytes() sur des fichiers de plus de 10 % du Heap disponible.

Création de Nombreux Objets dans une Boucle

La création intensive d'objets dans une boucle sans GC intermédiaire peut entraîner OOM, en particulier sur les appareils avec un petit Heap. Exemple : générer 100 000 objets dans une boucle for qui ne tiennent pas dans le Heap avant que le GC ne puisse les collecter. C'est plus fréquent dans les jeux et les éditeurs graphiques.

Utilisez Object Pool pour les objets créés et détruits en masse. Pour les données numériques, utilisez des primitives (FloatArray au lieu de List<Float>). RecyclerView avec ViewHolder Pool résout ce problème pour les composants d'interface.

Fragmentation du Heap

La fragmentation est un état où il y a suffisamment de mémoire libre au total, mais aucun bloc contigu pour un nouvel objet. ART compacte le Heap pendant le GC, mais pas toujours avec succès. Les grands tableaux (Bitmap, byte[]) sont les plus sensibles à la fragmentation.

ART sur Android 8+ utilise le GC Générationnel, qui réduit la fragmentation en séparant les objets jeunes et vieux. Néanmoins, évitez d'allouer des fragments de différentes tailles dans le même pool — essayez d'utiliser des tampons préalloués de taille fixe.

Limites de Heap sous Android

La limite de Heap sous Android n'est pas une constante — elle dépend du fabricant, du modèle d'appareil et de la version de l'OS. Google définit les exigences minimales via le document CDD (Compatibility Definition Document), mais les fabricants définissent les valeurs réelles.

Catégorie d'appareilHeap TypiquelargeHeap
Économique (1–2 Go RAM)128–192 Mo256–384 Mo
Moyenne gamme (3–4 Go RAM)256–384 Mo512 Mo
Flagship (6+ Go RAM)384–512 Mo768 Mo–1 Go
Tablettes (4+ Go RAM)256–512 Mo768 Mo
Wear OS32–64 MoN/A

Vous pouvez demander une limite augmentée via android:largeHeap="true" dans le manifeste. Utilisez-le avec précaution : augmenter le Heap ne résout pas le problème de fuites et peut aggraver l'expérience utilisateur si le système est obligé de tuer d'autres applications pour libérer de la mémoire pour la vôtre. Pour Wear OS, la limite de Heap est minimale — seulement 32 à 64 Mo, largeHeap n'est pas disponible ici, et l'économie de mémoire est doublement critique.

Diagnostic de OutOfMemoryError

Le diagnostic d'OOM nécessite l'analyse d'un Heap Dump et la compréhension des objets qui consomment la mémoire. Android Studio fournit tous les outils nécessaires.

Étape 1 : Capturez le moment de l'OOM. Dans Android Memory Profiler, cliquez sur Record memory allocations et exécutez le scénario qui provoque le plantage. Le Profiler montrera un pic d'allocations avant l'OOM. Si l'OOM n'est pas reproductible, réduisez le Heap via android:smallHeap dans la build de débogage ou utilisez DDMS avec appel manuel de GC.

Étape 2 : Prenez un Heap Dump au moment de la charge maximale (avant l'OOM). Ouvrez le Dump dans Android Studio : l'onglet Classes est trié par Retained Size. Les plus grands objets sont Bitmap, byte[], String. Pour chaque Bitmap, vérifiez la taille (largeur × hauteur × 4 octets) et le chemin de chargement via Stack Trace.

Étape 3 : Analysez le nombre d'objets en double. Si vous voyez 200 Fragment ou Activity identiques — c'est une fuite. Si 500 Bitmap avec la même taille — c'est un problème de cache d'images. MAT (Memory Analyzer Tool) fournit une analyse plus approfondie avec un Dominator Tree montrant quels objets retiennent 80 % du Heap.

text
// Commande Heap Dump via adb
adb shell am dumpheap com.example.app /data/local/tmp/dump.hprof
adb pull /data/local/tmp/dump.hprof.

Stratégies de prévention d'OOM

Une stratégie complète de prévention d'OOM comprend cinq niveaux de protection : des décisions architecturales à la surveillance en production.

Décisions Architecturales

ViewModel + Repository sépare les données de l'interface utilisateur et empêche la rétention de la View lors de la rotation de l'écran. La ViewModel survit à l'Activity, ses données ne sont pas perdues et la View peut être recréée sans dupliquer les données en mémoire. Utilisez StateFlow au lieu de LiveData pour une gestion explicite des états.

Gestion des Bitmap et Images

Glide est une bibliothèque obligatoire pour travailler avec les images. Elle redimensionne, met en cache (disque + mémoire) et recycle automatiquement les Bitmap. Configurez diskCacheStrategy et skipMemoryCache pour les grandes listes. Pour les images animées, utilisez Glide avec GIF/WebP — ils occupent moins de mémoire qu'une séquence de Bitmaps.

Surveillance en Production

Firebase Performance Monitoring suit la consommation mémoire en temps réel. Définissez une alerte lorsque l'utilisation du Heap dépasse 80 % de la limite — c'est un signal pour enquêter. Crashlytics collecte OOM comme une exception et montre le dernier état connu du Heap avant le plantage. Pour Android 11+, utilisez ApplicationExitInfo pour détecter les terminaisons OOM.

Tests sur Appareils Faibles

Assurez-vous de tester l'application sur des appareils avec un Heap minimal (128–192 Mo). Un émulateur avec un petit écran et un petit Heap émule un appareil économique. Si l'application fonctionne sur un tel appareil, il n'y aura pas de problèmes d'OOM sur les flagships. Utilisez Firebase Test Lab avec des appareils réels de différentes gammes de prix.

kotlin
// Vérification du Heap disponible avant opération lourde
fun canAllocate(requiredBytes: Long): Boolean {
    val runtime = Runtime.getRuntime()
    val free = runtime.freeMemory()
    return free > requiredBytes * 2 // marge de 50 %
}

FAQ

Peut-on attraper OutOfMemoryError avec try-catch ?

Techniquement oui, mais ce n'est pas recommandé. Après OOM, l'application est dans un état instable : de nouvelles allocations peuvent échouer et certains objets peuvent être partiellement créés. La seule action raisonnable dans catch est la journalisation et le redémarrage de l'Activity.

Pourquoi OOM ne se produit-il pas sur tous les appareils ?

La limite de Heap varie selon les appareils. Une opération qui nécessite 300 Mo plantera sur un appareil avec une limite de 192 Mo mais réussira sur un flagship avec 512 Mo. Testez sur des appareils avec des spécifications minimales pour détecter les scénarios OOM.

Comment largeHeap affecte-t-il les performances ?

largeHeap augmente la limite mais n'accélère pas l'application. Les pauses du GC deviennent plus longues car collecter un grand Heap prend plus de temps. Le système peut tuer des applications en arrière-plan pour fournir de la mémoire. Utilisez largeHeap uniquement pour les applications qui ont objectivement besoin de beaucoup de mémoire (caméras, éditeurs).

En quoi OOM diffère-t-il d'un kill système ?

OOM est une exception à l'intérieur d'une application lorsque le Heap est insuffisant. Un kill système (Low Memory Killer) est une décision du noyau Linux de tuer un processus pour libérer de la mémoire pour d'autres applications. Lors d'un kill système, l'application ne reçoit pas d'exception — le processus se termine simplement.

Combien de mémoire un Bitmap consomme-t-il réellement ?

La formule : largeur × hauteur × bytesPerPixel. ARGB_8888 = 4 B/pixel, RGB_565 = 2 B/pixel. Un Bitmap FullHD (1920 × 1080) en ARGB_8888 = 8,3 Mo. Un Bitmap 4K (3840 × 2160) = 33 Mo. Redimensionnez toujours les images à la taille nécessaire pour l'affichage à l'écran.

Résumé

  • OutOfMemoryError — une exception fatale lorsque la limite de Heap de l'application est épuisée
  • Bitmap sans redimensionnement — le principal coupable d'OOM dans les applications mobiles
  • Les fuites mémoire causent 70 % des OOM par accumulation d'objets à chaque transition
  • Limite de Heap varie de 128 Mo sur les appareils économiques à 512 Mo sur les flagships
  • Heap Dump avec analyse Retained Size — l'outil principal pour diagnostiquer OOM
  • Glide ou Coil sont obligatoires pour travailler avec des images de toute taille
  • Les tests sur appareils avec Heap minimal sont indispensables pour tous les projets

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