Préface
J'ai vu une question sur segmentfault: Java a un mécanisme GC complet, il y aura donc un problème de fuite de mémoire en Java, et puis-je donner un cas de fuite de mémoire. Cette vue de question donne la réponse complète à cette question.
Introduction au mécanisme de recyclage des ordures
Pendant l'exécution du programme, chaque objet est créé, une certaine quantité de mémoire est allouée pour stocker des données d'objet. Si vous continuez à allouer la mémoire, le programme sera confronté au problème de la mémoire insuffisante tôt ou tard. Ainsi, dans n'importe quelle langue, il y aura un mécanisme de récupération de la mémoire pour libérer la mémoire des objets expirés pour s'assurer que la mémoire peut être réutilisée.
Le mécanisme de recyclage de la mémoire peut être divisé en deux types en fonction des rôles de mise en œuvre. L'une est que les programmeurs réalisent manuellement la libération de la mémoire (comme le langage C) et l'autre est le mécanisme de recyclage de la mémoire intégré de la langue, comme le mécanisme de collecte des ordures Java à introduire dans cet article.
Mécanisme de collecte des ordures de Java
Dans l'environnement d'exécution du programme, la machine virtuelle Java fournit un fil de collection d'ordures au niveau du système (GC, collection de carbage), qui est responsable de la récupération de la mémoire occupée par des objets qui ont perdu des références. La condition préalable à la compréhension de GC est de comprendre certains concepts liés à la collecte des ordures. Ces concepts sont introduits un par un dans ce qui suit.
L'état de l'objet dans la zone de tas JVM
Les instances d'objets Java sont stockées dans la zone de tas de JVM. Pour les threads GC, ces objets ont trois états.
1. État touchant: il existe des références de variables dans le programme, donc cet objet est un étatocalable.
2. État réactivé: Lorsqu'aucune variable dans le programme se réfère à cet objet, l'objet passera d'un état touchant à un état réactivé. Le thread CG se préparera à appeler la méthode finalisée de cet objet à un certain moment (la méthode Finalise hérite ou réécrit l'objet enfant). Le code de la méthode finalisée peut convertir l'objet en un état de contact, sinon l'objet sera converti en un état intouchable.
3. État intouchable: le thread GC ne peut recycler la mémoire de cet objet que lorsque l'objet est dans un état intouchable.
Afin de libérer correctement les objets, GC doit surveiller l'état de fonctionnement de chaque objet, y compris l'application, la citation, la citation, l'attribution, etc. GC doit le surveiller, donc GC saura, quel que soit un objet dans un état ci-dessus.
Comme mentionné ci-dessus, les threads GC exécuteront la méthode Finalize des objets d'état ressusciables à un certain moment. Alors, quand sera-t-il exécuté? Étant donné que différents implémentateurs JVM peuvent utiliser différents algorithmes pour gérer GC, à tout moment, les développeurs ne peuvent pas prédire le calendrier des threads GC effectuant diverses opérations (y compris la détection de l'état d'objet, la libération de la mémoire d'objet et l'appel finalisent des méthodes). Bien que le fil GC puisse être rappelé à effectuer des opérations de collecte des ordures dès que possible via les fonctions System.gc () et runtime.gc (), cela ne peut garantir que le thread GC effectuera immédiatement les opérations de recyclage correspondantes.
Fuite de mémoire
Les fuites de mémoire sont causées par de mauvaises conceptions que le programme ne publie pas de mémoire qui n'est plus utilisée, ce qui entraîne un gaspillage de ressources. GC nettoiera automatiquement la mémoire occupée par des objets qui ont perdu des références. Cependant, si certains objets sont toujours référencés en raison d'erreurs de programmation, une fuite de mémoire se produira.
Par exemple, l'exemple suivant. Un tableau est utilisé pour implémenter une pile, avec deux opérations: entrée de pile et sortie de pile.
Importer com.sun.javafx.collections.elementObservableLlistDecorator; Import com.sun.swing.internal.pllaf.metal.resources.metal_sv; import java.beans.exceptionlistener; import java.util.emptystackexception; / ** * créé par pesg sur 14-9-21. * / public class MyStack {objet privé [] Elements; Incrément INT privé = 10; private int size = 0; public mystack (int size) {elements = nouvel objet [taille]; } // Mettez la pile public void push (objet o) {capacile (); éléments [taille ++] = o; } // Mettez l'objet public Stack PORT () {if (size == 0) lancez New videStacKexception (); Éléments de retour [- taille]; } // augmenter la capacité de la capacité de vide privée de pile () {if (elements.length! = Size) return; Objet [] newArray = nouvel objet [elements.length + incrément]; System.ArrayCopy (Elements, 0, NewArray, 0, taille); } public static void main (string [] args) {mystack stack = new MyStack (100); pour (int i = 0; i <100; i ++) stack.push (nouvel entier (i)); for (int i = 0; i <100; i ++) {System.out.println (stack.pop (). toString ()); }}}Ce programme est disponible et prend en charge les opérations d'entrée de pile et d'entrée de pile communes. Cependant, il y a un problème qui n'a pas été bien géré, c'est-à-dire que lorsque l'opération de pile est libérée, la référence à l'élément de pile dans le tableau n'est pas libérée, ce qui fait que le programme conserve une référence à cet objet (cet objet est référencé par le tableau). GC croit toujours que cet objet est accessible, ce qui signifie qu'il n'est pas nécessaire de parler de la libération de sa mémoire. Il s'agit d'un cas typique de fuites de mémoire. Pour cela, le code modifié est:
// Stack Public Object POP () {if (size == 0) lance un nouveau videstacKexception (); Objet o = éléments [- taille]; éléments [taille] = null; retour o; }L'article ci-dessus a une compréhension approfondie du mécanisme de collecte des ordures Java et des fuites de mémoire. C'est tout le contenu que j'ai partagé avec vous. J'espère que cela pourra vous donner une référence et j'espère que vous pourrez soutenir Wulin.com plus.