En Java, sa gestion de la mémoire comprend deux aspects: l'allocation de mémoire (lors de la création d'objets Java) et le recyclage de la mémoire. Les deux aspects du travail sont automatiquement achevés par le JVM, réduisant la difficulté d'apprendre pour les programmeurs Java et évitant le danger de faire fonctionner directement la mémoire comme C / C ++. Cependant, c'est précisément parce que la gestion de la mémoire est entièrement gérée par le JVM que de nombreux programmeurs Java ne se soucient plus de l'attribution de la mémoire, ce qui fait que de nombreux programmes sont inefficaces et consommateurs de mémoire. Par conséquent, les programmeurs Java doivent comprendre le JVM à la fin afin d'écrire des programmes plus efficaces et de faire un usage complet de la mémoire limitée.
1. State de Java en mémoire
Tout d'abord, écrivons un code comme exemple:
Personne.java
Test de package; Importer java.io.serializable; la classe de classe publique implémente Serializable {static final long SerialVersionUID = 1l; Nom de chaîne; // Nommez un ami de la personne; // Amis Public Person () {} Person public (nom de chaîne) {super (); this.name = name; }} Test.java
Test de package; Test de classe publique {public static void main (String [] args) {personne p1 = new personne ("kevin"); Personne p2 = nouvelle personne ("pluie"); Personne P3 = nouvelle personne ("Sunny"); p1.friend = p2; p3 = p2; p2 = null; }} Si vous dessinez la référence d'objet dans l'aspect principal de Test.java ci-dessus dans un diagramme de référence d'objet à partir de la méthode principale, c'est comme ça (les sommets sont des objets et des références, et les arêtes dirigées sont des relations de référence):
Lorsque le programme s'exécute, une fois considéré comme un graphique dirigé, il peut être divisé en trois types:
1) État réalisable: Une fois un objet créé, plus d'une variable de référence y fait référence. Dans un graphique dirigé, vous pouvez naviguer vers l'objet à partir du sommet de départ, et il est dans un état accessible.
2) État récupérable: Si un objet dans le programme n'a plus de variables de référence en y faisant référence, il entrera d'abord dans l'état redoutable, et à l'heure actuelle, il ne peut pas naviguer vers l'objet à partir du sommet de départ du graphique dirigé. Dans cet état, le mécanisme de collecte des ordures du système est prêt à recycler la mémoire occupée par l'objet. Avant le recyclage, le système appellera la méthode finaliser () pour nettoyer la ressource. Si plusieurs variables de référence sont récupérées après le tri de la ressource, l'objet redeviendra un état accessible; Sinon, il entrera dans un état inaccessible.
3) État inaccessible: lorsque toutes les associations de l'objet sont coupées et que le système appelle la méthode finalisée () pour nettoyer la ressource ne rend toujours pas l'état accessible, alors l'objet perdra définitivement la référence et deviendra un état inaccessible, et le système recyclera vraiment les ressources occupées par l'objet.
Le diagramme de transition des trois états ci-dessus est le suivant:
2. 4 Références aux objets de Java
1) Référence forte: créez un objet et attribuez cet objet directement à une variable, par exemple: personne personne = new personne ("Sunny"); Peu importe à quel point les ressources du système sont serrées, l'objet référencé fort ne sera jamais recyclé, même s'il ne sera plus utilisé à l'avenir.
2) Soft Reference: Implémenté via la classe Softreference, par exemple: Softreference <ponon> p = Nouveau Softreference <ponse> (nouvelle personne ("Rain")); lorsque la mémoire est très serrée, elle sera recyclée et ne sera pas recyclée à d'autres moments, donc avant de l'utiliser, vous devez déterminer s'il est nul pour déterminer s'il a été recyclé.
3) Référence faible: mise en œuvre par le biais de la classe de référence faible, par exemple: FaibleReference <ponge> p = new FaibleReference <onon> (nouvelle personne ("pluie")); Peu importe si la mémoire est suffisante, le système sera certainement recyclé lors de la collecte des ordures.
4) Citation virtuelle: il ne peut pas être utilisé seul, il est principalement utilisé pour suivre l'état de l'objet collecté par les ordures. Implémenté via la classe PhantomReference et la classe de référence de référence de référence, par exemple:
Test de package; import java.lang.ref.phantomreference; import java.lang.ref.referenceeue; public class test {public static void main (String [] args) {// créer une personne d'objet personne = new personne ("sunny"); // Créer une file d'attente de référence ReferenceQueue <ponse> rq = new ReferenceQueue <onom> (); // Créez une référence virtuelle, laissez cette référence virtuelle de référence à l'objet de la personne Phantomreference <ponse> Pr = new Phantomreference <ponge> (Person, RQ); // régler les variables de référence et les objets des références de personne personne = null; // Essayez de sortir l'objet référencé par la référence virtuelle // J'ai constaté que le programme ne peut pas accéder à l'objet référencé via la référence virtuelle, donc la sortie ici est null System.out.println (pr.get ()); // Système de collecte des ordures forcés.gc (); System.Runfinalisation (); // Étant donné qu'une fois l'objet dans la référence virtuelle recyclée, la référence virtuelle entrera la file d'attente de référence // Utilisez donc la référence entrée d'abord la file d'attente dans la file d'attente pour comparer avec PR, et out out la sortie System.out.println (rq.poll () == pr); }}Résultats en cours:
3. Mécanisme de collecte des ordures Java
En fait, la collection Java Garbage fait principalement deux choses: 1) le recyclage de la mémoire 2) la défragmentation
3.1 Algorithme de collecte des ordures
1) Recyclage en série (un seul processeur) et recyclage parallèle (plusieurs CPU sont utiles): le recyclage en série signifie que peu importe le nombre de processeurs du système, il ne s'agit toujours d'un seul processeur pour effectuer des opérations de collecte de déchets. Le recyclage parallèle signifie diviser l'ensemble des travaux de recyclage en plusieurs parties, chaque partie étant responsable par un processeur, afin que plusieurs CPU puissent être recyclés en parallèle. Le recyclage parallèle est très efficace dans l'exécution, mais il augmente la complexité, et il y a aussi certains effets secondaires, tels que l'augmentation aléatoire de la mémoire.
2) Exécution et arrêt d'application simultanés: Comme son nom l'indique, sa méthode de collecte des ordures entraînera une suspension d'application lors de la collecte des ordures. Bien que la collecte des ordures d'une exécution simultanée ne provoquera pas la pause de l'application, car une exécution simultanée doit résoudre les conflits avec l'application (l'application peut modifier des objets pendant le processus de collecte des ordures), les frais généraux du système d'une exécution simultanée de la collecte des ordures sont plus élevés que celle de l'arrêt du monde, et nécessite plus de mémoire de tas lors de l'exécution.
3) Comprimer et non compresser et copier:
① Le collecteur des ordures qui prend en charge la compression (compression mark = compression mark-clear +) déplacera tous les objets accessibles ensemble, puis recyclera toute la mémoire précédemment occupée, réduisant la fragmentation de la mémoire.
② Le collecteur de déchets non compressé (marque-claire) doit être traversé deux fois. La première fois que vous accédez d'abord à tous les objets accessibles et les marquez comme des états accessibles. La deuxième fois que vous facilite la zone de mémoire et le recyclage des objets qui ne sont pas des états accessibles marqués. Cette méthode de recyclage n'est pas compressée et ne nécessite pas de mémoire supplémentaire, mais elle produira une fragmentation si elle prend deux traversées.
③ Copier le collecteur des ordures: divisez la mémoire du tas en deux espaces identiques, accédez à chaque objet accessible associé à partir de la racine (similaire au sommet de départ du graphique dirigé précédent), copiez tous les objets accessibles dans l'espace A pour l'espace B, puis recyclez l'espace A à la fois. Pour cet algorithme, car il vous suffit d'accéder à tous les objets accessibles, de copier tous les objets accessibles et de recycler directement l'espace entier, en ignorant du tout les objets inaccessibles, le coût de la traversée de l'espace est petit, mais il nécessite d'énormes coûts de copie et plus de mémoire.
3.2 Recyclage générationnel de la mémoire du tas
1) La base du recyclage générationnel:
①La durée du temps de survie de l'objet: La plupart des objets sont recyclés pendant la période jeune ② Différentes générations adoptent différentes stratégies de recyclage des ordures: Nouveau (temps de survie court) ancien (temps de survie long) ont rarement des références entre les objets
2) Génération de la mémoire du tas:
① jeune génération:
Mécanisme de recyclage: Parce que le nombre d'objets est petit, la réplication et le recyclage sont utilisés.
Ⅱ Zone de consolidation: Il se compose de 1 zone d'Eden et 2 zones de survivants. Deux zones de survivant en même temps, l'une est utilisée pour sauver l'objet et l'autre est vide; Chaque fois que la collection de déchets de jeune génération est réalisée, les objets accessibles à Eden et à partir de sont copiés dans la zone à la zone, et certains des longues durées de vie sont copiés dans la vieillesse, puis l'Eden et de l'espace sont dégagés, et enfin l'original à l'espace devient de l'espace, et l'original de l'espace devient à l'espace.
Ⅲ Source d'objets: la plupart des objets sont d'abord affectés à la zone Eden, et certains grands objets seront attribués directement à l'ancienne génération.
Ⅳ Fréquence de recyclage: comme la plupart des jeunes objets de génération entrent rapidement dans un état inaccessible, la fréquence de recyclage est élevée et la vitesse de recyclage est rapide.
Génération: génération:
Mécanisme de réduction: utilisez l'algorithme de compression de marque pour récupérer.
Ⅱ Source d'objets: 1. Le grand objet entre directement dans la vieillesse.
2. Recyclage la fréquence des objets accessibles avec un long temps de survie dans la jeune génération: comme peu d'objets meurent, la fréquence d'exécution n'est pas élevée et il faut beaucoup de temps.
Génération permanente:
ⅠPurpose: Utilisé pour charger la classe, la méthode et d'autres informations. La valeur par défaut est de 64 m et ne sera pas recyclée. ⅡObject Source: EG: Pour les frameworks comme Hibernate et Spring qui, comme les classes de génération dynamique AOP, génèrent souvent un grand nombre de classes de proxy dynamiques, donc plus de mémoire de génération permanente est nécessaire. Nous rencontrons donc souvent java.lang.outofMemoryError: Permgen Space Erreur lors du débogage de l'hibernate. Il s'agit de l'erreur causée par l'épuisement de la mémoire de génération permanente.
Ⅲ Fréquence de recyclage: ne sera pas recyclé
3.3 Collecteurs de déchets communs
1) Recycleur en série (un seul CPU est utilisé): Young Generation utilise l'algorithme de copie série; L'ancienne génération utilise l'algorithme de compression de Mark Serial (trois étapes: Mark Mark - Clear Sweep - Compress Compact), le programme sera interrompu pendant la période de recyclage.
2) Recycleur parallèle: l'algorithme utilisé pour la jeune génération est le même que le recycleur en série, mais il ajoute seulement un traitement parallèle multi-CPU; Le traitement de l'ancienne génération est exactement le même que celui du recycleur en série, et est toujours un seul fil.
3) Collecteur de compression parallèle: Le traitement de la jeune génération est exactement le même algorithme que celui du collecteur parallèle; Mais différents algorithmes sont utilisés pour l'ancienne génération, qui est en fait divisé en différentes régions, puis en algorithme d'étiquetage et de compression:
① Divisez vieux en plusieurs zones fixes;
② étape de marque (parallèle multithread), marquant des objets accessibles;
③ Étape de résumé (exécution en série). Lorsque vous trouvez une zone qui atteint la valeur numérique (faible densité des objets) à partir de la gauche, cette zone et sa zone droite sont compressées et récupérées. L'extrémité gauche est l'étape dense de la zone compacte (parallèle multi-thread), identifier les zones qui doivent être chargées et copier les données dans ces zones en parallèle. Après ce processus, il y a un grand nombre d'objets actifs à une extrémité de l'ancienne génération et un grand espace à l'autre extrémité.
4) Identification simultanée - Nettoyage et recyclage (CMS): Le traitement de la jeune génération est exactement le même algorithme que celui des recycleurs parallèles; Mais différents algorithmes sont utilisés pour l'ancienne génération, mais l'algorithme de nettoyage de Mark est toujours utilisé:
① Identification initiale (pause du programme): marque l'objet directement référencé (objet de premier niveau);
② Identification simultanée (RUN du programme): Trouvez d'autres objets accessibles via des objets de premier niveau;
③ REMARK (PAUSE DU PROGRAMME): objets de recouvrement parallèle multi-thread qui peuvent avoir été manqués en raison de la concurrence (simplement parlant, c'est anti-manque)
④ Nettoyage simultané (Runs de programme)
4. Conseils de gestion de la mémoire
1) Essayez d'utiliser la quantité directe, par exemple: String javastr = "Le processus de croissance de l'apprentissage des écoles primaires";
2) Utilisez StringBuilder et StringBuffer pour effectuer une concaténation de chaîne et d'autres opérations;
3) Libérez les objets inutiles dès que possible;
4) Essayez d'utiliser le moins possible des variables statiques;
5) Cache objets couramment utilisés: peut être implémenté à l'aide du cache open source open source, par exemple: oscache, ehcache;
6) Essayez de ne pas utiliser la méthode finaliser ();
7) Vous pouvez envisager d'utiliser une soft de référence de référence si nécessaire.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.