59 votes

JVM 64 bits limitée à 300 Go de mémoire ?

J'essaie d'exécuter une application Java sur un environnement informatique en grappe (IBM LSF exécutant CentOS version 6.2 Final) qui peut me fournir jusqu'à 1 To d'espace RAM.

Je pourrais créer une JVM avec jusqu'à 300 Go de mémoire maximale (Xmx), bien que j'aie besoin de plus que cela (je peux fournir des détails, si on me le demande).

Cependant, il semble impossible de créer une JVM avec plus de 300 Go de mémoire maximale en utilisant l'option Xmx. Pour être plus précis, j'obtiens le message d'erreur classique :

Une erreur s'est produite pendant l'initialisation de la VM.

Impossible de réserver assez d'espace pour le tas d'objets.

Les détails de ma JVM (64-bit) sont ci-dessous :

Environnement d'exécution OpenJDK (IcedTea6 1.10.6) (rhel-1.43.1.10.6.el6_2-x86_64)

VM serveur OpenJDK 64-Bit (build 20.0-b11, mode mixte)

J'ai également essayé avec une JVM Java 7 64 bits mais j'ai eu exactement le même problème.

De plus, j'ai essayé de créer une JVM pour exécuter un HelloWorld.jar, mais la création de la JVM échoue toujours si vous demandez plus que -Xmx300G, donc je ne pense pas que cela ait quelque chose à voir avec l'application spécifique.


Quelqu'un a-t-il une idée de la raison pour laquelle je ne peux pas créer une JVM avec plus de 300G de mémoire maximale ?

Quelqu'un peut-il suggérer une solution ou un moyen de contournement ?

18voto

Stephen C Points 255558

Je peux penser à quelques explications possibles :

  • D'autres applications sur votre système utilisent tellement de mémoire qu'il n'y a pas 300 Go. disponible dès maintenant .

  • Il pourrait y avoir une limite de ressources sur la taille de la mémoire par processus. Vous pouvez le vérifier en utilisant ulimit . (Notez que selon ce problème vous obtiendrez le message d'erreur si la limite de ressources par processus empêche la JVM d'allouer les régions du tas).

  • Il est également possible qu'il s'agisse d'un problème de "surcommission" ; par exemple, si votre application est exécutée dans un virtuel et que le système dans son ensemble ne peut pas répondre à la demande parce qu'il y a trop de concurrence avec d'autres virtuels.


Quelques-unes des autres idées suggérées sont (IMO) peu probables :

  • Il est peu probable que le changement de JRE fasse une différence. Je n'ai jamais vu ou entendu parler de limites de mémoire arbitraires dans des JVM 64 bits spécifiques.

  • Il est peu probable qu'elle soit due à un manque de contiguës mémoire. Il est certain qu'une mémoire physique contiguë n'est pas nécessaire. La seule possibilité serait un espace contigu sur le périphérique d'échange, mais je ne me souviens pas que ce soit un problème pour les systèmes d'exploitation Linux typiques.


Quelqu'un peut-il suggérer une solution ou un moyen de contournement ?

  • Vérifiez le ulimit .

  • Ecrivez un petit programme en C qui essaie de malloc beaucoup de mémoire et voir combien il peut en allouer avant d'échouer.

  • Demandez de l'aide à l'administrateur du système (ou de l'hyperviseur).

15voto

Abel Points 24335

(édité, voir section ajoutée sur l'espace d'échange)

SHMMAX et SHMALL

Puisque vous utilisez CentOS, il se peut que vous ayez rencontré un problème similaire au sujet de l'interface de l'utilisateur. SHMMAX y SHMALL réglage du noyau comme décrit ici pour configurer la base de données Oracle . Sous ce même lien se trouve un exemple de calcul permettant d'obtenir et de définir les bons paramètres de l'indice de référence. SHMALL réglage.

Mémoire contiguë

Certains utilisateurs ont déjà signalé qu'il n'y avait pas assez de mémoire contiguë disponible, d'autres ont dit que ce n'était pas pertinent.

Je ne suis pas certain que la JVM de CentOS nécessite un bloc de mémoire contigu. Selon SAS En effet, la mémoire fragmentée peut empêcher votre JVM de démarrer avec une grande capacité de mémoire maximale. Xmx ou commencer Xms mais d'autres affirmations sur Internet disent que cela n'a pas d'importance. J'ai essayé de prouver ou d'infirmer cette affirmation sur ma station de travail Windows de 48 Go, mais j'ai réussi à démarrer la JVM avec un paramètre initial et maximal de 40 Go. Je suis pratiquement sûr qu'aucun bloc contigu de cette taille n'était disponible, mais les JVM sur différents systèmes d'exploitation peuvent se comporter différemment, car la gestion de la mémoire peut être différente d'un système d'exploitation à l'autre (par exemple, Windows cache généralement les adresses physiques des processus individuels).

Trouver le plus grand bloc de mémoire contigu

Utilice /proc/meminfo pour trouver le plus grand bloc de mémoire contigu disponible, voir la valeur sous VmAllocChunk . Voici un guide et une explication de toutes les valeurs. Si la valeur que vous voyez là est inférieure à 300 Go, essayez une valeur qui se situe juste en dessous de la valeur de VmAllocChunk .

Cependant, ce nombre est généralement plus élevé que la mémoire physiquement disponible (car il s'agit de la virtuel valeur de mémoire disponible), il peut vous donner un faux positif. C'est la valeur que vous pouvez réserver, mais une fois que vous commencez à l'utiliser, elle peut nécessiter un swapping. Vous devez donc également vérifier la valeur MemFree et le Inactive valeurs. À l'inverse, vous pouvez également examiner l'ensemble de la liste et voir quelles valeurs ne dépassent pas 300 Go.

Autres options de réglage que vous pouvez vérifier pour la JVM 64 bits

Je ne sais pas pourquoi vous semblez rencontrer un problème de limite de mémoire à 300 Go. Pendant un moment, j'ai pensé que vous aviez atteint un maximum de pages. Avec la valeur par défaut de 4kB, 300GB donne 78,643,200 pages. Cela ne ressemble pas à un nombre magique bien connu. Si, par exemple, 2^24 est le maximum, alors 16,777,216 pages, soit 64 Go, devrait être votre maximum théorique allouable.

Cependant, supposons, pour les besoins de l'argumentation, que vous ayez besoin de pages plus grandes (ce qui est, comme il s'avère, meilleur pour les performances des applications Java à grande mémoire), vous devriez consultez cette page de manuel sur JBoss qui explique comment utiliser -XX:+UseLargePages et mettre kernel.shmmax (c'est reparti), vm.nr_hugepages y vm.huge_tlb_shm_group (je ne suis pas sûr que cette dernière soit nécessaire).

Mettez votre système sous tension

D'autres l'ont déjà suggéré également. Pour vous assurer que le problème vient de la JVM et non du système d'exploitation, vous devriez effectuer un stresstest. Un outil que vous pouvez utiliser est Stresslinux . Dans ce tutoriel vous trouverez quelques options que vous pouvez utiliser. La commande suivante présente un intérêt particulier pour vous :

stress --vm 2 --vm-bytes 300G --timeout 30s --verbose

Si cette commande échoue ou bloque votre système, vous savez que le système d'exploitation limite l'utilisation de cette quantité de mémoire. Si elle réussit, nous devons essayer de modifier la JVM pour qu'elle puisse utiliser la mémoire disponible.

EDIT Avr6 : vérifier l'espace de swap

Il n'est pas rare que les systèmes dotés d'une mémoire interne très importante n'utilisent que peu ou pas d'espace d'échange. Pour de nombreuses applications, cela peut ne pas être un problème, mais la JVM exige que l'espace d'échange disponible soit plus grand que la taille de la mémoire demandée. D'après ce rapport de bogue la JVM essaiera d'augmenter elle-même l'espace d'échange, cependant, comme le montrent certaines réponses dans la rubrique ce fil de discussion SO a suggéré la JVM n'est pas toujours capable de le faire.

Par conséquent, vérifiez l'espace d'échange actuellement disponible avec cat /proc/swaps # free et, s'il est inférieur à 300 Go, suivez les instructions suivantes les instructions de cette page de manuel CentOS pour augmenter l'espace d'échange de votre système.

Note 1 : on peut déduire de rapport de bogue n° 4719001 qu'un contiguës d'espace swap disponible n'est pas une nécessité. Mais si vous n'êtes pas sûr, supprimer tout l'espace d'échange et le recréer ce qui devrait supprimer toute fragmentation.

Note 2 : J'ai vu plusieurs messages comme celui-ci reporting 0MB espace de permutation y être capable d'exécuter la JVM. Cela est probablement dû au fait que la JVM augmente elle-même l'espace d'échange. Vous pouvez toujours essayer d'augmenter l'espace d'échange à la main pour voir si cela résout votre problème.

Conclusion prématurée

Je réalise qu'aucune des réponses ci-dessus n'est une réponse toute faite à votre question. J'espère cependant vous donner quelques pistes pour essayer de faire fonctionner votre JVM. Vous pouvez également essayer d'autres JVM, si le problème s'avère être une limite de la JVM que vous utilisez actuellement, mais d'après ce que j'ai lu jusqu'à présent, aucune limite ne devrait être imposée pour les JVM 64 bits.

Le fait que vous obteniez l'erreur dès l'initialisation de la JVM m'incite à penser que le problème ne vient pas de la JVM, mais du fait que le système d'exploitation n'est pas en mesure de respecter la réservation des 300 Go de mémoire.

Mes propres tests ont montré que la JVM peut accéder à toute la mémoire virtuelle, et ne se soucie pas de la quantité de mémoire physique disponible. Il serait étrange que la mémoire virtuelle soit inférieure à la mémoire physique, mais la VmAllocChunk devrait vous donner un indice dans cette direction (il est généralement beaucoup plus grand).

4voto

Shishir Kumar Points 2273

Si vous jetez un coup d'œil à la Section FAQ de la Java HotSpot VM, il est mentionné que sur les VM 64 bits, il n'y a que 64 bits d'adresse avec lesquels travailler et donc la taille maximale du tas Java dépend de la quantité de mémoire physique et de l'espace d'échange présents sur le système.

Si vous calculez théoriquement, alors vous pouvez avoir une mémoire de 18446744073709551616 MB mais il y a des limites à cela.

Vous devez utiliser -Xmx pour définir la taille maximale du tas pour la JVM, Par défaut Java utilise 64 + 30% = 83,2 Mo sur les JVM 64 bits.

J'ai essayé la commande ci-dessous sur ma machine et cela semble fonctionner correctement.

java -Xmx500g com.test.TestClass

J'ai également essayé de définir le tas maximum en téraoctets mais cela ne fonctionne pas.

0voto

user3100381 Points 134

Exécutez ulimit -a en tant qu'utilisateur du processus JVM et vérifiez que votre noyau ne limite pas la taille maximale de votre mémoire. Vous devrez peut-être modifier le fichier /etc/security/limit.conf.

0voto

Aleksandr Dubinsky Points 2488

Según cette discussion Le LSF ne regroupe pas la mémoire des nœuds dans un espace partagé unique. Vous utilisez quelque chose d'autre pour cela. Lisez la documentation de cet autre outil, car il est possible qu'il ne puisse pas faire ce que vous lui demandez. En particulier, il se peut qu'il ne soit pas en mesure d'allouer un unique contiguës région de la mémoire qui s'étend sur tous les nœuds. En général, ce n'est pas nécessaire, car une application fera de nombreux appels à malloc. Mais la JVM, pour se simplifier les choses, veut allouer (ou réserver) une seule région contiguë pour l'ensemble du tas en appelant effectivement malloc une seule fois. Ou cela pourrait être quelque chose d'autre lié à ce que vous utilisez pour émuler une machine à mémoire partagée géante.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X