web-dev-qa-db-fra.com

Comprendre l'allocation de mémoire JVM et Java Out of Memory: Heap Space

Je cherche vraiment à comprendre comment fonctionne l'allocation de mémoire dans la JVM. J'écris une application dans laquelle je récupère de la mémoire: exceptions d'espace de tas.

Je comprends que je peux transmettre des arguments VM tels que Xms et Xmx pour augmenter l'espace de mémoire que la JVM alloue pour le processus en cours d'exécution. C'est une solution possible au problème, ou je peux inspecter mon code pour les fuites de mémoire et résoudre le problème là-bas.

Mes questions sont:

1) Comment la JVM s’alloue-t-elle réellement la mémoire? Comment cela se rapporte-t-il à la façon dont le système d'exploitation communique la mémoire disponible à la JVM? Ou plus généralement, comment fonctionne l'allocation de mémoire pour tout processus?

2) Comment la mémoire virtuelle entre-t-elle en jeu? Disons que vous avez un système avec 32 Go de mémoire physique et que vous allouez les 32 Go à votre processus Java. Supposons que votre processus consomme réellement les 32 Go de mémoire, comment pouvons-nous appliquer le processus à utiliser de la mémoire virtuelle au lieu d'exécuter des exceptions OOM?

Merci.

24
HiChews123

Comment la JVM alloue-t-elle réellement la mémoire?

Pour le tas, il alloue une grande zone de mémoire conitnous de la taille maximale. Au départ, il s'agit de mémoire virtuelle, mais avec le temps, elle devient une véritable mémoire pour les parties utilisées, sous le contrôle du système d'exploitation.

Quel est le lien avec la façon dont le système d'exploitation communique la mémoire disponible à la JVM?

La JVM n'a aucune idée de la mémoire disponible dans le système d'exploitation.

Ou plus généralement, comment fonctionne l'allocation de mémoire pour tout processus?

En général, il utilise malloc et gratuit.

Comment la mémoire virtuelle entre-t-elle en jeu?

Initialement, la mémoire virtuelle est allouée et cela se transforme en mémoire réelle telle qu'elle est utilisée. Ceci est normal pour tout processus.

Disons que vous avez un système avec 32 Go de mémoire physique et que vous allouez les 32 Go à votre processus Java.

Tu ne peux pas. Le système d'exploitation a besoin de mémoire et il y aura de la mémoire à d'autres fins. Même au sein de la JVM, le segment de mémoire n'est qu'une partie de la mémoire utilisée. Si vous disposez de 32 Go de mémoire, je suggère un tas de 24 Go max.

Disons que votre processus consomme en fait les 32 Go de mémoire,

Supposons que vous disposez de 48 Go et que vous démarrez un processus qui utilise 32 Go de mémoire principale.

comment pouvons-nous appliquer le processus pour utiliser la mémoire virtuelle au lieu d'exécuter des exceptions OOM?

L'application utilise la mémoire virtuelle dès le début. Vous ne pouvez pas rendre le tas trop grand, car s'il commence à échanger votre machine (et pas seulement votre application), elle deviendra inutilisable.

Vous pouvez utiliser plus de mémoire que vous n'en avez physiquement en utilisant soigneusement la mémoire hors segment. Cependant, la mémoire gérée doit être dans la mémoire physique, donc si vous avez besoin d'un tas de 32 Go, achetez 64 Go de mémoire principale.

23
Peter Lawrey

La JVM (ou d'ailleurs n'importe quel processus) qui veut allouer de la mémoire appellera la fonction d'exécution C ' malloc '. Cette fonction gère la mémoire de tas du runtime C. À son tour, il obtient la mémoire du noyau du système d'exploitation - la fonction utilisée pour cela dépend de la plate-forme; sous Linux, il pourrait utiliser les appels système brk ou sbrk .

Une fois que la mémoire a été obtenue par la JVM, elle gère la mémoire elle-même, en allouant des parties de celle-ci aux différents objets créés par le programme en cours d'exécution.

La mémoire virtuelle est entièrement gérée par le noyau du système d'exploitation. Le noyau gère le mappage des pages de mémoire physique avec l'espace d'adressage de divers processus; s'il y a moins de mémoire physique que celle requise par tous les processus du système, le noyau du système d'exploitation en échangera une partie sur le disque.

Vous ne pouvez pas (et n'avez pas besoin de) forcer les processus à utiliser la mémoire virtuelle. Il est transparent pour votre processus.

Si vous obtenez des erreurs de "mémoire insuffisante", les causes sont probablement les suivantes:

  1. Les limites de la JVM sont dépassées. Ceux-ci sont contrôlés par divers arguments et/ou propriétés de ligne de commande comme vous l'avez indiqué dans votre question

  2. L'OS peut avoir manqué d'espace de swap (ou ne pas avoir d'espace de swap configuré pour commencer). Ou certains systèmes d'exploitation ne prennent même pas en charge la mémoire virtuelle, auquel cas vous n'avez plus de mémoire réelle.

  3. La plupart des systèmes d'exploitation ont des fonctionnalités permettant à l'administrateur de limiter la quantité de mémoire consommée par un processus - par exemple, sous Linux, l'appel système setrlimit et/ou la commande ulimit Shell, qui définissent toutes deux les limites que le noyau va observer. Si un processus demande plus de mémoire que ce qui est autorisé par les limites, la tentative échoue (généralement, cela entraîne un message de mémoire insuffisante).

7
harmic
  1. La JVM alloue Java mémoire de tas du système d'exploitation, puis gère le tas pour l'application Java. Lorsqu'une application crée un nouvel objet, la JVM sous-alloue une zone contiguë de mémoire de segment pour la stocker. Un objet du segment référencé par un autre objet est "actif" et reste dans le segment tant qu'il continue d'être référencé. Les objets qui ne sont plus référencés sont des ordures et peut être effacé du tas pour récupérer l'espace qu'ils occupent. La machine virtuelle Java effectue un garbage collection (GC) pour supprimer ces objets, en réorganisant les objets restants dans le tas.
    Source: http://pubs.vmware.com/vfabric52/index.jsp?topic=/com.vmware.vfabric.em4j.1.2/em4j/conf-heap-management.html

  2. Dans un système utilisant la mémoire virtuelle, la mémoire physique est divisée en pages de taille égale. La mémoire adressée par un processus est également divisée en pages logiques de même taille. Lorsqu'un processus fait référence à une adresse mémoire, le gestionnaire de mémoire extrait du disque la page qui contient l'adresse référencée et la place dans une page physique libre de la RAM.

Source: http://searchstorage.techtarget.com/definition/virtual-memory

2
Little Child

Ce blog examine Java utilisation de la mémoire que vous pourriez trouver utile:

http://www.waratek.com/blog/november-2013/introduction-to-real-world-jvm-memory-utilisation

2
ElastiCat