En Java, la gestion de la mémoire est effectuée par le biais de la collecte automatique des déchets (Garbage Collector, GC). La JVM suit les objets en mémoire : si un objet n’a plus de références, il devient inaccessible et peut être supprimé.
Le GC se compose de différentes phases, telles que Mark, Sweep et parfois Compact. Dans la phase Mark, les objets accessibles depuis les racines (GC roots) sont marqués comme vivants. Après cela, commence la phase Sweep : les objets non utilisés sont supprimés. Parfois, Compact est exécuté — la défragmentation de la mémoire.
Il existe différents types de GC : Serial, Parallel, CMS, G1. Ils doivent être choisis en fonction du type de charge sur l'application.
List<byte[]> dataList = new ArrayList<>(); while(true) { dataList.add(new byte[1024*1024]); // Les objets restent accessibles }
Dans cet exemple, les objets ne deviendront jamais inaccessibles, le GC ne les supprimera pas, et cela entraînera un OutOfMemoryError.
Si un objet n’a plus de références, quand est-il garanti que son finaliseur (finalize()) sera appelé ?
Réponse : L'appel de la méthode finalize() n'est pas du tout garanti ! Il peut ne pas être appelé ou être appelé avec un retard. On ne peut pas compter sur finalize() pour libérer des ressources.
@Override protected void finalize() throws Throwable { // Peut ne pas fonctionner ! }
Histoire
Dans un grand système de e-commerce, les développeurs espéraient automatiser le nettoyage des fichiers temporaires en utilisant la méthode finalize(), mais en raison de l'appel rare de cette méthode, le cache a débordé de fichiers temporaires, entraînant un manque d'espace disque et des temps d'arrêt.
Histoire
Dans un API REST à forte charge, un cache interne de références à de grands objets a été sauvegardé par inadvertance, ce qui a empêché la libération de mémoire. Après un crash de l'application avec OutOfMemoryError, une analyse a révélé une erreur dans la méthode de mise en cache.
Histoire
Des finaliseurs ont été utilisés pour libérer des connexions réseau, considérées comme "un moyen sûr". Cela a conduit à des connexions qui restaient dans le système pendant une durée indéfinie, provoquant des blocages et l'épuisement du pool de connexions.