L'éditeur suivant vous apportera une compréhension approfondie des stratégies d'allocation de mémoire et de recyclage Java. L'éditeur le trouve plutôt bon, je vais donc le partager avec vous maintenant et le donner comme référence pour tout le monde. Suivons l'éditeur et jetons un coup d'œil.
1. Introduction
La gestion automatique de la mémoire mentionnée dans le système technologique Java concerne en fin de compte la mémoire. . Concernant les deux problématiques d'allocation et de recyclage, je vous ai déjà parlé du recyclage Java. Aujourd'hui, je vais vous parler de l'allocation des objets Java en mémoire. En termes simples, l'allocation mémoire des objets est une allocation sur le tas. Les objets sont principalement alloués sur Eden de nouvelle génération (la génération des objets en mémoire sera complétée lors du garbage collection. Si vous souhaitez en savoir plus, vous pouvez également vous référer "Compréhension approfondie de la machine virtuelle Java"), si le tampon d'allocation de thread local est démarré, il sera alloué sur le TLAB en fonction de la priorité du thread. Dans quelques cas, il est également attribué directement à l'ancienne génération.
2. Stratégie d'allocation classique
1. Les objets sont alloués en premier sur Eden <.>
Généralement, les objets sont d'abord alloués sur Eden. Lorsqu'Eden n'a pas assez d'espace pour l'allocation, jvm lancera un GC mineur. S'il n'y a toujours pas assez d'espace alloué, il existe d'autres mesures, qui seront mentionnées ci-dessous. Définissez le paramètre de journal impair de la machine virtuelle -XX:+PrintGCDetails Pendant le garbage collection, le journal de recyclage de la mémoire sera imprimé et lorsque le processuspublic class ReflectTest { private static final int _1MB = 1024*1024; public static void testAllocation(){ byte[] allocation1 , allocation2 , allocation3 , allocation4; allocation1 = new byte[2 * _1MB]; allocation2 = new byte[2 * _1MB]; allocation3 = new byte[2 * _1MB]; allocation4 = new byte[6 * _1MB]; } public static void main(String[] args) { ReflectTest.testAllocation(); } }
Heap PSYoungGen total 9216K, used 6651K [0x000000000b520000, 0x000000000bf20000, 0x000000000bf20000) eden space 8192K, 81% used [0x000000000b520000,0x000000000bb9ef28,0x000000000bd20000) from space 1024K, 0% used [0x000000000be20000,0x000000000be20000,0x000000000bf20000) to space 1024K, 0% used [0x000000000bd20000,0x000000000bd20000,0x000000000be20000) PSOldGen total 10240K, used 6144K [0x000000000ab20000, 0x000000000b520000, 0x000000000b520000) object space 10240K, 60% used [0x000000000ab20000,0x000000000b120018,0x000000000b520000) PSPermGen total 21248K, used 2973K [0x0000000005720000, 0x0000000006be0000, 0x000000000ab20000) object space 21248K, 13% used [0x0000000005720000,0x0000000005a07498,0x0000000006be0000)
2. Les objets volumineux sont directement alloués dans l'ancienne génération
Les objets volumineux font référence aux objets qui nécessitent une grande quantité d'espace mémoire continu pour store, similaire au genre depublic class ReflectTestBig { private static final int _1MB = 1024*1024; public static void testAllocation(){ byte[] allocation2 , allocation3 , allocation4; allocation2 = new byte[2 * _1MB]; allocation3 = new byte[2 * _1MB]; allocation4 = new byte[6 * _1MB]; } public static void main(String[] args) { ReflectTestBig.testAllocation(); } }
Heap PSYoungGen total 8960K, used 4597K [0x000000000b510000, 0x000000000bf10000, 0x000000000bf10000) eden space 7680K, 59% used [0x000000000b510000,0x000000000b98d458,0x000000000bc90000) from space 1280K, 0% used [0x000000000bdd0000,0x000000000bdd0000,0x000000000bf10000) to space 1280K, 0% used [0x000000000bc90000,0x000000000bc90000,0x000000000bdd0000) PSOldGen total 10240K, used 6144K [0x000000000ab10000, 0x000000000b510000, 0x000000000b510000) object space 10240K, 60% used [0x000000000ab10000,0x000000000b110018,0x000000000b510000) PSPermGen total 21248K, used 2973K [0x0000000005710000, 0x0000000006bd0000, 0x000000000ab10000) object space 21248K, 13% used [0x0000000005710000,0x00000000059f7460,0x0000000006bd0000)
3. Les objets survivants à long terme entreront dans l'ancienne génération
Puisque la machine virtuelle adopte l'idée de collecte de bandes pour gérer mémoire, la mémoire Recyclage doit identifier quels objets doivent être placés dans la nouvelle génération et quels objets doivent être placés dans l'ancienne génération. Afin d'atteindre cet objectif, jvm définit un compteur d'âge (Age) pour chaque objet. Si l'objet est né en Eden et survit au premier GC mineur, et peut être stocké dans le Survivant, il sera déplacé vers le Survivant et l'âge de l'objet sera fixé à 1. Chaque fois qu'un objet échappe au GC Mineur, son âge sera augmenté de 1. Lorsque son âge dépassera le seuil d'un an, l'objet sera promu à l'ancienne génération. Ce seuil jvm est par défaut de 15 et peut être défini par -XX:MaxTenuringThreshold.public class JavaTest { static int m = 1024 * 1024; public static void main(String[] args) { byte[] a1 = new byte[1 * m / 4]; byte[] a2 = new byte[7 * m]; byte[] a3 = new byte[3 * m]; //GC } }
[GC [DefNew: 7767K->403K(9216K), 0.0062209 secs] 7767K->7571K(19456K), 0.0062482 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] a3 ok Heap def new generation total 9216K, used 3639K [0x331d0000, 0x33bd0000, 0x33bd0000) eden space 8192K, 39% used [0x331d0000, 0x334f9040, 0x339d0000) from space 1024K, 39% used [0x33ad0000, 0x33b34de8, 0x33bd0000) to space 1024K, 0% used [0x339d0000, 0x339d0000, 0x33ad0000) tenured generation total 10240K, used 7168K [0x33bd0000, 0x345d0000, 0x345d0000) the space 10240K, 70% used [0x33bd0000, 0x342d0010, 0x342d0200, 0x345d0000) compacting perm gen total 12288K, used 381K [0x345d0000, 0x351d0000, 0x385d0000) the space 12288K, 3% used [0x345d0000, 0x3462f548, 0x3462f600, 0x351d0000) ro space 10240K, 55% used [0x385d0000, 0x38b51140, 0x38b51200, 0x38fd0000) rw space 12288K, 55% used [0x38fd0000, 0x396744c8, 0x39674600, 0x39bd0000)
4. Détermination dynamique de l'âge des objets
Afin de mieux s'adapter à l'état de la mémoire des différents programmes, les machines virtuelles ne nécessitent pas toujours d'objets. L'âge doit atteindre la valeur fixée par -XX:MaxTenuringThreshold pour être promu à l'âge avancé. Si la somme des tailles de tous les objets du même âge dans l'espace Survivant est supérieure à la moitié de l'espace Survivant, les objets dont l'âge est supérieur ou égal à cet âge peut saisir directement l'âge de la vieillesse, il n'est pas nécessaire d'atteindre la valeur de réglage dans -XX:MaxTenuringThreshold.5. Garantie d'attribution d'espace
Lorsque un GC mineur se produit, la machine virtuelle détectera si la taille moyenne de chaque promotion vers l'ancienne génération est supérieure à l'espace restant de l'ancienne génération. Si elle est supérieure, un GC COMPLET sera effectué directement. S'il est inférieur à, vérifiez si le paramètre HandlerPromotionFailyre autorise l'échec de la garantie. S'il est autorisé, seul le GC mineur sera effectué. S'il n'est pas autorisé, un GC FUll sera également amélioré. C'est-à-dire que lorsque la nouvelle génération Eden ne peut pas stocker l'objet modifié, l'objet sera stocké dans l'ancienne génération.
3. Paramètres des paramètres jvm couramment utilisés
1 -Xms : taille de tas initiale, tas libre par défaut (le paramètre MinHeapFreeRatio peut être ajusté). mémoire Lorsqu'il est inférieur à 40%, la JVM augmentera le tas jusqu'à la limite maximale de -Xmx.
2.
3. -Xmn : Taille de la jeune génération (1,4 ou lator), la taille ici est (eden + 2 espace survivant) Elle est différente de la nouvelle génération affichée dans jmap -heap.
La taille entière du tas = taille de la jeune génération + taille de l'ancienne génération + taille de la génération persistante.
Après avoir augmenté la jeune génération, la taille de l'ancienne génération sera réduite. Cette valeur a un plus grand impact sur les performances du système. Sun recommande officiellement une configuration de 3/8 de l'ensemble du tas.
4. -XX:NewSize : Définissez la taille de la jeune génération (pour 1,3/1,4).
5. -XX:MaxNewSize : La valeur maximale de la jeune génération (pour 1,3/1,4).
6. -XX:PermSize : Définit la valeur initiale de la génération persistante (perm gen).
7. -XX:MaxPermSize : Définissez la taille maximale de la génération persistante.
8. -Xss : La taille de la pile de chaque thread. Après JDK5.0, la taille de la pile de chaque thread était de 1 Mo. Dans le passé, la taille de la pile de chaque thread était de 256 Ko. le thread d'application peut être ajusté.. Sous la même mémoire physique, réduire cette valeur peut générer plus de threads. Cependant, le système d'exploitation a toujours des limites sur le nombre de threads dans un processus et ne peut pas être généré à l'infini. ~5000.
9. -XX:NewRatio : Le ratio de la jeune génération (y compris Eden et deux zones Survivor) à l'ancienne génération (à l'exclusion de la génération persistante), -XX:NewRatio=4 signifie la différence entre les jeunes. génération et ancienne génération La valeur du ratio est de 1:4 et la jeune génération représente 1/5 de la pile entière. Lorsque Xms=Xmx et Xmn sont définis, ce paramètre n'a pas besoin d'être défini.
10. -XX:SurvivorRatio : Le rapport de taille de la zone Eden et de la zone Survivant est fixé à 8, puis le rapport de deux zones Survivant pour une zone Eden est de 2:8, et une zone Survivant représente pour toute la jeune génération.
11. -XX:LargePageSizeInBytes : La taille de la page mémoire ne peut pas être trop grande, ce qui affectera la taille de Perm.
12. -XX:+DisableExplicitGC : Close System.gc()
13. -XX:MaxTenuringThreshold : L'âge maximum des déchets. passer par la zone Survivor, entrer directement dans l'ancienne génération. Pour les applications avec un grand nombre d'anciennes générations, l'efficacité peut être améliorée si cette valeur est définie sur une valeur plus grande, les objets de la jeune génération seront copiés plusieurs fois dans la zone Survivor, afin que plus d'objets puissent être ajoutés. Le temps de survie de la jeune génération augmente la probabilité d'être recyclé dans la jeune génération. Ce paramètre n'est efficace qu'en série GC.
14. -XX:PretenureSizeThreshold : Si l'objet dépasse la taille, il est alloué directement dans l'ancienne génération. L'octet d'unité n'est pas valide lorsque la nouvelle génération utilise Parallel Scavenge GC. Une autre situation où il est alloué directement. dans l'ancienne génération, il y a un grand tableau Object, et il n'y a pas d'objet de référence externe dans le tableau.
15. -XX:TLABWasteTargetPercent : Le pourcentage de TLAB dans la zone eden.
4. Supplément
La différence entre le GC mineur et le GC FUll :
GC de nouvelle génération (GC mineur) : fait référence à l'action de récupération de place qui se produit dans la nouvelle génération. Parce que la plupart des objets Java ne peuvent pas échapper au premier tour de GC, le GC mineur est fréquemment utilisé. la vitesse de recyclage est généralement plus rapide.
GC ancienne génération (FULL GC/Major GC) : fait référence au GC qui survient dans l'ancienne génération. Lorsque le Major GC apparaît, il est souvent accompagné d'au moins un Minor GC (. mais pas absolument, dans La stratégie de collecte du collecteur ParallelScavenge inclut le processus de sélection directe du Major GC). La vitesse du Major GC est généralement plus de 10 fois plus lente que celle du Minor GC.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!