Comment le pool de mémoire Java est-il divisé?

224

Je surveille actuellement une application Java avec jconsole. L'onglet mémoire vous permet de choisir entre:

Heap Memory Usage
Non-Heap Memory Usage
Memory Pool “Eden Space”
Memory Pool “Survivor Space”
Memory Pool “Tenured Gen”
Memory Pool “Code Cache”
Memory Pool “Perm Gen”

Quelle est la différence entre eux ?

Dani Cricco
la source
En supposant que vous utilisez le Sun JDK, la meilleure réponse se trouve dans leur documentation: Tuning Garbage Collection (JDK 1.5) et Garbage Collection FAQ (JDK 1.4)
kdgregory

Réponses:

327

Mémoire de tas

La mémoire de tas est la zone de données d'exécution à partir de laquelle la machine virtuelle Java alloue de la mémoire pour toutes les instances de classe et les tableaux. Le tas peut être de taille fixe ou variable. Le garbage collector est un système de gestion de mémoire automatique qui récupère la mémoire de tas pour les objets.

  • Eden Space : pool à partir duquel la mémoire est initialement allouée à la plupart des objets.

  • Espace Survivant : La piscine contenant des objets qui ont survécu à la collecte des ordures de l'espace Eden.

  • Tenured Generation ou Old Gen : le pool contenant des objets qui existent depuis un certain temps dans l'espace survivant.

Mémoire non tas

La mémoire non segmentée comprend une zone de méthode partagée entre tous les threads et la mémoire requise pour le traitement interne ou l'optimisation de la machine virtuelle Java. Il stocke des structures par classe telles qu'un pool de constantes d'exécution, des données de champ et de méthode, et le code des méthodes et des constructeurs. La zone de méthode fait logiquement partie du tas mais, selon l'implémentation, une machine virtuelle Java peut ne pas récupérer ou compacter la mémoire. Comme la mémoire de tas, la zone de méthode peut être de taille fixe ou variable. La mémoire de la zone de méthode n'a pas besoin d'être contiguë.

  • Génération permanente : pool contenant toutes les données réfléchissantes de la machine virtuelle elle-même, telles que les objets de classe et de méthode. Avec les machines virtuelles Java qui utilisent le partage de données de classe, cette génération est divisée en zones en lecture seule et en lecture-écriture.

  • Cache de code : la machine virtuelle Java HotSpot comprend également un cache de code, contenant de la mémoire utilisée pour la compilation et le stockage de code natif.

Voici de la documentation sur l'utilisation de Jconsole .

dfa
la source
4
Je ne suis pas sûr que @dfa soit complètement correct, comme l'indique clairement la spécification de la machine virtuelle Java: «Bien que la zone de méthode fasse logiquement partie du tas, les implémentations simples peuvent choisir de ne pas récupérer les ordures ou les compacter.» Cependant, il est clair que jconsole affiche le cache de code et la génération permanente comme non-tas, ce qui semble contredire la spécification. Quelqu'un peut-il apporter plus de précisions sur cette contradiction?
James Bloom
@JamesBloom - Je me demandais la même chose. Même si la définition de base indique quel pool de mémoire appartient à quel type (tas / non-tas), il pourrait changer son état de manière explicite?
Umang Desai
2
le doc dont il a été surnommé: docs.intergral.com/pages/viewpage.action?pageId=22478944 Le doc contient quelques autres bonnes informations sur la JVM, qui valent le détour
Steve Siebert
1
Malgré beaucoup de votes positifs, ce n'est pas une réponse si significative, en fait. Par exemple, que signifie «les objets qui ont survécu à la collecte des ordures de l'espace Eden»? Ces objets sont-ils déplacés vers l'Espace Survivant d'Eden après avoir survécu, ou leur espace dans l'Eden est-il considéré comme un espace Survivant? Et qu'en est-il de la collecte des ordures dans les piscines autres que l'espace Eden, cela se produit-il? Pas du tout clair.
Mikhail Batcer
et n'oubliez pas la pile (du côté non-tas) :)
Toothless Seer
70

Le nouveau mot clé alloue de la mémoire sur le tas Java. Le tas est le principal pool de mémoire, accessible à l'ensemble de l'application. S'il n'y a pas assez de mémoire disponible pour allouer à cet objet, la JVM tente de récupérer de la mémoire du tas avec un garbage collection. S'il ne parvient toujours pas à obtenir suffisamment de mémoire, une erreur OutOfMemoryError est levée et la JVM se ferme.

Le tas est divisé en plusieurs sections différentes, appelées générations. Au fur et à mesure que les objets survivent à davantage de collectes de déchets, ils sont promus dans différentes générations. Les générations plus âgées ne sont pas ramassées aussi souvent. Parce que ces objets ont déjà prouvé leur durée de vie plus longue, ils sont moins susceptibles d'être récupérés.

Lorsque les objets sont construits pour la première fois, ils sont attribués dans l'Espace Eden. S'ils survivent à une collecte des ordures, ils sont promus dans l'espace des survivants et s'ils y vivent assez longtemps, ils sont attribués à la génération permanente. Cette génération est des déchets collectés beaucoup moins fréquemment.

Il existe également une quatrième génération, appelée la génération permanente, ou PermGen. Les objets qui résident ici ne sont pas éligibles pour être récupérés et contiennent généralement un état immuable nécessaire à l'exécution de la JVM, comme les définitions de classe et le pool de constantes String. Notez que l'espace PermGen devrait être supprimé de Java 8 et sera remplacé par un nouvel espace appelé Metaspace, qui sera conservé en mémoire native. référence: http://www.programcreek.com/2013/04/jvm-run-time-data-areas/

entrez la description de l'image ici entrez la description de l'image ici

Pythoner
la source
Le diagramme semble très explicite ... Est-ce valable pour tout algorithme GC. G1 ont un ensemble différent.
Venkateswara Rao
@Pythoner Je pense que le drapeau en violet foncé devrait être -XX:PermSizeet non -XX:MaxPermSizetel qu'il est déjà défini ci-dessus.
Anurag
35

Avec Java8, la région non tas ne contient plus PermGen mais Metaspace, qui est un changement majeur dans Java8, censé se débarrasser des erreurs de mémoire avec java car la taille de la métaspace peut être augmentée en fonction de l'espace requis par jvm pour les données de classe.

user2767149
la source
1
En fait, il y a de la métaspace et de l'espace de classe: docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/…
mrswadge
23

Java Heap Memory fait partie de la mémoire allouée à JVM par le système d'exploitation.

Les objets résident dans une zone appelée tas. Le segment de mémoire est créé au démarrage de la JVM et peut augmenter ou diminuer de taille pendant l'exécution de l'application. Lorsque le tas est plein, les déchets sont collectés.

entrez la description de l'image ici

Vous pouvez trouver plus de détails sur Eden Space, Survivor Space, Tenured Space et Permanent Generation dans la question ci-dessous SE:

Génération jeune, permanente et permanente

PermGen a été remplacé par Metaspace depuis la sortie de Java 8.

Concernant vos requêtes:

  1. Eden Space, Survivor Space, Tenured Space font partie de la mémoire du tas
  2. Metaspace et Code Cache font partie de la mémoire non-tas.

Codecache: la machine virtuelle Java (JVM) génère du code natif et le stocke dans une zone de mémoire appelée codecache. La machine virtuelle Java génère du code natif pour diverses raisons, y compris pour la boucle d'interpréteur générée dynamiquement, les stubs JNI (Java Native Interface) et pour les méthodes Java qui sont compilées en code natif par le compilateur juste à temps (JIT). Le JIT est de loin le plus gros utilisateur du cache de codage.

Ravindra babu
la source