« Salut ! J'ai décidé de te donner une autre petite leçon sur le ramassage des ordures.
Comme vous le savez déjà, la machine Java elle-même surveille lorsqu'un objet devient inutile et le supprime.
"Ouais. Toi et Rishi m'en avez parlé plus tôt. Je ne me souviens pas des détails."
"OK. Alors revenons dessus."
« Dès qu'un objet est créé, la JVM lui alloue de la mémoire. L'intérêt pour l'objet est contrôlé à l'aide de variables de référence . objet. "
"Parlez-moi un peu du ramasse-miettes, de quoi il s'agit et comment il fonctionne."
"OK. La récupération de place se produisait sur le thread principal. Toutes les 5 minutes, ou plus souvent. S'il n'y avait jamais assez de mémoire libre, la machine Java suspendait tous les threads et supprimait les objets inutilisés."
"Mais cette approche a été abandonnée maintenant. Le ramasse-miettes de nouvelle génération fonctionne dans les coulisses et sur un thread séparé. C'est ce qu'on appelle le ramasse-miettes simultané."
"Je vois. Comment exactement la décision de supprimer un objet est-elle prise ou non ?"
"Le simple fait de compter le nombre de références à un objet n'est pas très efficace - il peut y avoir des objets qui se référencent les uns les autres, mais qui ne sont référencés par aucun autre objet."
"Java adopte donc une approche différente. Java divise les objets en accessibles et inaccessibles. Un objet est accessible (vivant) s'il est référencé par un autre objet accessible (vivant). L'accessibilité est déterminée à partir des threads. Les threads en cours d'exécution sont toujours considérés comme accessibles (vivants). , même si personne ne les mentionne."
"OK. Je pense que j'ai compris."
"Comment se passe le ramasse-miettes ? La suppression des objets inutiles ?"
"C'est simple. En Java, la mémoire est divisée en deux parties par convention, et quand vient le temps de la récupération de place, tous les objets vivants (accessibles) sont copiés dans une autre partie de la mémoire, et l'ancienne mémoire est entièrement libérée."
"C'est une approche intéressante. Pas besoin de compter les références : copiez tous les objets accessibles, et tout le reste est inutile."
"C'est un peu plus compliqué que cela. Les programmeurs Java ont découvert que les objets sont généralement divisés en deux catégories : à longue durée de vie (qui existent tout au long de l'exécution du programme) et à courte durée de vie (qui sont nécessaires dans les méthodes et pour effectuer des opérations "locales". » opérations)."
"Il est beaucoup plus efficace de séparer les objets à longue durée de vie de ceux à courte durée de vie. Pour ce faire, il était nécessaire de trouver un moyen de déterminer la longévité de l'objet."
"Donc, ils ont divisé toute la mémoire en "générations". Il y a des objets de première génération, des objets de deuxième génération, etc. Chaque fois que la mémoire est effacée, le compteur de génération est incrémenté de 1. Si certains objets existent dans plusieurs générations, alors ils sont enregistrées comme ayant une longue durée de vie."
"Aujourd'hui, le ramasse-miettes est une partie très complexe et efficace de Java. Beaucoup de ses parties fonctionnent de manière heuristique, basée sur des algorithmes qui font des suppositions. En conséquence, il "n'écoute pas" souvent l'utilisateur."
"Signification?"
"Java a un objet garbage collector ( GC ) qui peut être appelé à l'aide de la méthode System.gc ()."
"Vous pouvez également utiliser System.runFinalization() pour forcer les appels aux méthodes finalize des objets à supprimer. Mais le fait est que, selon la documentation Java, cela ne garantit ni que le ramasse-miettes démarre, ni que le finalize( ) sera appelée. Le ramasse-miettes décide quand l'appeler et sur quoi. "
"Ouah ! Bon à savoir."
"Mais il y a plus. Comme vous le savez, en Java, certains objets en référencent d'autres. Ce réseau de références est utilisé pour déterminer si un objet doit être supprimé."
"Et, regardez. Java a des références spéciales qui vous permettent d'influencer ce processus. Il existe des classes wrapper spéciales pour elles. Les voici :"
" SoftReference est une référence logicielle."
" WeakReference est une référence faible."
" PhantomReference est une référence fantôme."
"Euh... Cela me rappelle les classes internes, les classes imbriquées, les classes anonymes imbriquées et les classes locales. Les noms sont différents, mais on ne sait pas du tout à quoi ils servent."
"Dites, Amigo, vous êtes devenu programmeur. Maintenant, vous êtes en colère à cause des noms de classe, en disant "ils ne sont pas assez informatifs, et il est impossible avec un seul nom (!) De déterminer ce que fait cette classe, comment, et pourquoi"."
"Wow. Je n'avais même pas remarqué. Mais c'est tellement évident."
"OK. Assez de mots. Laissez-moi vous parler de SoftReferences."
"Ces références ont été spécifiquement conçues pour la mise en cache, bien qu'elles puissent être utilisées à d'autres fins, le tout à la discrétion du programmeur."
"Voici un exemple d'une telle référence :"
// Create a Cat object
Cat cat = new Cat();
// Create a soft reference to a Cat object
SoftReference<Cat> catRef = new SoftReference<Cat>(cat);
// Now only the catRef soft reference points at the object
cat = null;
// Now the ordinary cat variable also references the object
cat = catRef.get();
// Clear the soft reference
catRef.clear();
"Si les seules références à un objet sont douces, alors il continue à vivre et est appelé" facilement accessible "."
"Mais! Un objet référencé uniquement par des références logicielles peut être supprimé par le ramasse-miettes si le programme n'a pas assez de mémoire. Si soudainement le programme n'a pas assez de mémoire, avant de lever une OutOfMemoryException , le ramasse-miettes supprimera tous les objets référencé par des références logicielles et essaiera à nouveau d'allouer de la mémoire au programme."
"Supposons qu'un programme client demande fréquemment diverses données à un programme serveur. Le programme serveur peut utiliser une SoftReference pour en mettre en cache certaines. Si des objets protégés de la mort par des références logicielles occupent une grande partie de la mémoire, le ramasse-miettes les supprime simplement. tout. C'est beau !"
"Ouais. J'ai aimé ça moi-même."
"Eh bien, un petit ajout : la classe SoftReference a deux méthodes. La méthode get() renvoie l'objet référencé par SoftReference . Si l'objet a été supprimé par le ramasse-miettes, la méthode get () commencera soudainement à renvoyer null."
"L'utilisateur peut également effacer explicitement SoftReference en appelant la méthode clear(). Dans ce cas, le lien faible à l'intérieur de l' objet SoftReference sera détruit."
"C'est tout pour le moment."
"Merci pour cette histoire intéressante, Ellie. C'était vraiment très intéressant."
GO TO FULL VERSION