web-dev-qa-db-fra.com

Java Refuse to Start - Impossible de réserver suffisamment d'espace pour le tas d'objets

Contexte

Nous avons un pool d'environ 20 lames Linux. Certains courent Suse, d'autres courent Redhat. ALL share NAS espace qui contient les 3 dossiers suivants:

  • / NAS/app/Java - lien symbolique pointant vers l'installation d'un JDK Java. Version actuelle 1.5.0_10
  • / NAS/app/lib - un lien symbolique qui pointe vers une version de notre application.
  • / NAS/data - répertoire dans lequel notre sortie est écrite

Toutes nos machines disposent de 2 processeurs (hyperthreaded) avec 4 Go de mémoire physique et 4 Go d’espace de permutation. Nous limitons le nombre de "travaux" que chaque machine peut traiter à un moment donné à 6 (ce nombre doit probablement changer, mais cela ne rentre pas dans le problème actuel, veuillez donc l'ignorer pour le moment).

Certains de nos travaux définissent une taille maximale du tas de 512 Mo, d'autres réservent une taille maximale du tas de 2048 Mo. De nouveau, nous réalisons que nous pourrions utiliser notre mémoire disponible si 6 travaux commencés sur la même machine avec la taille de segment de mémoire définie sur 2048, mais à notre connaissance, cela ne s'est pas encore produit.

Le problème

Une tâche échouera immédiatement avec le message suivant:

Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Auparavant, nous utilisions trop de tâches exécutées simultanément sur la même machine. Le problème est arrivé assez rarement ( PEUT-ÊTRE une fois par mois) que nous allions simplement le redémarrer et que tout irait bien.

Le problème a récemment empiré. Tous nos travaux qui demandent une taille de tas maximale de 2 048 m échouent immédiatement presque à chaque fois et doivent être redémarrés plusieurs fois avant la fin.

Nous sommes allés sur des machines individuelles et avons essayé de les exécuter manuellement avec le même résultat.

Débogage

Il s'avère que le problème n'existe que pour nos boîtes SuSE. Cela s’explique plus souvent par le fait que nous avons ajouté de nouvelles machines et que les nouvelles machines sont SuSE.

'cat/proc/version' sur les boîtes SuSE nous donne:

Linux version 2.6.5-7.244-bigsmp (geeko@buildhost) (gcc version 3.3.3 (SuSE Linux)) #1 SMP Mon Dec 12 18:32:25 UTC 2005

'cat/proc/version' sur les boîtes RedHat nous donne:

Linux version 2.4.21-32.0.1.ELsmp ([email protected]) (gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-52)) #1 SMP Tue May 17 17:52:23 EDT 2005

'uname -a' nous donne les informations suivantes sur les DEUX types de machines:

UTC 2005 i686 i686 i386 GNU/Linux

Aucune tâche n'est en cours d'exécution sur la machine et aucun autre processus n'utilise beaucoup de mémoire. Tous les processus en cours d'exécution peut-être utilisent un total de 100 Mo.

'top' affiche actuellement les éléments suivants:

Mem:   4146528k total,  3536360k used,   610168k free,   132136k buffers
Swap:  4194288k total,        0k used,  4194288k free,  3283908k cached

'vmstat' affiche actuellement les éléments suivants:

procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r  b   swpd   free   buff  cache   si   so    bi    bo   in    cs us sy id wa
0  0      0 610292 132136 3283908    0    0     0     2   26    15  0  0 100  0

Si nous lançons un travail avec la ligne de commande suivante (Max Heap of 1850mb), cela commence correctement:

Java/bin/Java -Xmx1850M -cp helloworld.jar HelloWorld
Hello World

Si nous augmentons la taille maximale du tas à 1875 Mo, elle échoue:

Java/bin/Java -Xmx1875M -cp helloworld.jar HelloWorld
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Il est bien évident que la mémoire actuellement utilisée est destinée à la mise en mémoire tampon et à la mise en cache, raison pour laquelle si peu est affichée comme étant "libre". Ce qui n’est pas clair, c’est pourquoi il existe une ligne magique de 1850 Mo où tout ce qui est plus haut signifie Java ne peut pas commencer.

Toute explication serait grandement appréciée.

49
Randyaa

Vous utilisez un système d'exploitation 32 bits, vous allez donc voir des limites sur la taille totale pour cette raison. D'autres réponses ont couvert cette question plus en détail, aussi j'éviterai de répéter leurs informations.

Un comportement que j’ai récemment remarqué avec nos serveurs est celui qui spécifie une taille de tas maximale avec -Xmx en ne spécifiant pas de taille de segment minimale avec -Xms _ conduirait au serveur de Java VM) qui tenterait immédiatement d’allouer toute la mémoire nécessaire à la taille maximale du segment de mémoire. Et bien sûr, si l’application atteint cette taille de segment, c’est la quantité de mémoire disponible. mais il est fort probable que vos applications démarreront avec des tas relativement petits et que peut nécessitera un segment de mémoire plus important à un moment ultérieur. En outre, en spécifiant la taille minimale du segment de mémoire, vous pourrez app commence avec un plus petit tas et grandit progressivement ce tas.

Tout cela ne va pas vous aider à augmenter la taille maximale de votre tas, mais je pensais que cela pourrait aider, alors ...

21
Jon Bright

Comme suggéré dans d'autres réponses, le problème est dû à l'épuisement de l'espace d'adressage virtuel. Un programme d’espace utilisateur Linux 32 bits est généralement limité à 3 Go d’AS; le noyau utilise 1 Go restant (justification: puisque le 1 Go supérieur est le mappage fixe du noyau, il n'est pas nécessaire de toucher le tableau des pages pour servir les appels système).

Les noyaux RHEL, cependant, implémentent la division dite 4 Go/4 Go, où l'AS complet de 4 Go est disponible pour les processus en espace utilisateur au prix d'une légère surcharge d'exécution (le noyau réside dans un AS virtuel de 4 Go séparé).

15
Luca Tettamanti

L'exécution d'un système d'exploitation 32 bits est une erreur. vous devriez certainement mettre à jour dès que possible.

Je ne sais pas si Java exige que son segment de mémoire se trouve dans un seul bloc contigu, mais si c'est le cas, demander 1,8 G de segment de mémoire sur une boîte de 32 bits sonne comme un défi de taille. Vous supposez qu'il existe un bloc d'espace d'adressage, presque la moitié, gratuit au moment du démarrage de la machine virtuelle Java.

En fonction des autres bibliothèques chargées à ce moment-là, il se peut que non. Les bibliothèques peuvent allouer de la mémoire où bon leur semble, de sorte que votre espace d'adressage puisse être suffisamment fragmenté pour que la version 1.8G ne soit pas disponible dans un seul bloc.

De toute façon, il n’ya qu’environ 32 espaces max. D’adresse 3G disponibles sur Linux 32 bits. Les bibliothèques et la machine virtuelle elle-même en utilisent certaines pour commencer.

8
MarkR

Il semble que pour les serveurs 32 bits, il existe une limitation JVM qui ne peut pas être surmontée (sauf si vous trouvez une JVM 32 bits spéciale qui n'impose pas une limite de 2 Go ou moins).

Ce fil sur le côté serveur contient plus de détails, y compris plusieurs personnes qui ont testé diverses machines virtuelles sur des architectures 32 bits. La machine virtuelle Java d'IBM semble autoriser 100 Mo supplémentaires, mais cela ne vous donnera pas vraiment ce que vous voulez.

http://www.theserverside.com/discussions/thread.tss?thread_id=26347

La "vraie" solution consiste à utiliser un serveur 64 bits avec une JVM 64 bits pour obtenir des tas de plus de 2 Go par processus. Cependant, il est important de prendre également en compte l'impact de l'augmentation de la taille de votre adresse (pas uniquement de l'espace adressable) à l'aide d'une JVM 64 bits. Des performances et des impacts en termes de mémoire liés au traitement utilisant moins de 4 Go de mémoire seront probablement présents.

Matière à réflexion: chacun de ces travaux nécessite-t-il réellement 2 Go de mémoire? Existe-t-il un moyen de modifier les travaux dans 1,8 Go afin que cette limite ne pose pas de problème?

4
Brion

J'ai écrit deux applications, l'une de taille moyenne et l'autre assez petite. J'allais lancer celui de taille moyenne (sur linux, centos), sans aucun argument, (serveur Java), et tout irait bien. Mais lorsque j'ai ensuite lancé l'application plus petite avec "client Java", elle m'a dit qu'elle ne pouvait pas réserver assez d'espace et ne pouvait pas s'exécuter. J'ai expérimenté et utilisé les -Xms et -Xmx avec 10m, et ils courraient tous les deux sans se plaindre ... Allez comprendre!

3
murf

ulimit max memory size et mémoire virtuelle configurée pour illimité?

3
Andrew

J'ai mis à niveau la mémoire d'une machine de 2 Go à 4 Go et j'ai immédiatement commencé à avoir l'erreur:

$ Java -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Le problème était le ulimit, que j'avais fixé à 1 Go pour l'espace adressable. L'augmentation à 2 Go a résolu le problème.

-Xms et -Xmx n'ont eu aucun effet.

On dirait que Java tente d'obtenir de la mémoire proportionnellement à la mémoire disponible et échoue s'il ne le peut pas.

2
Penz

Vous devez envisager de mettre à niveau votre système d'exploitation et Java. Java 5.0 est EOL, mais si vous ne pouvez pas mettre à jour vers Java 6, vous pouvez utiliser le dernier correctif de niveau 22!

Windows 32 bits est limité à environ 1,3 Go. Vous vous en tirez donc bien avec un maximum de 1,8. Remarque: il s’agit d’un problème de mémoire continue et, à mesure que votre système fonctionne, son espace mémoire peut être fragmenté, ce qui ne me surprend pas.

Un système d’exploitation 64 bits n’a pas ce problème car il dispose de beaucoup plus d’espace virtuel, vous n’avez même pas besoin de passer à une version 64 bits de Java pour en tirer parti.

En passant, d'après mon expérience, Java 5.0 32 bits peut être plus rapide que Java 5.0 64 bits. De nombreuses années plus tard, Java 6 mise à jour 10 était plus rapide en 64 bits.

2
Peter Lawrey

J'ai récemment fait face à ce problème. J'ai 3 Java qui commencent par une taille de segment de mémoire de 1024 m ou 1280 m. Java examine l'espace disponible dans le swap et s'il n'y a pas assez de mémoire disponible.) , le jvm sort.

Pour résoudre le problème, je devais arrêter plusieurs programmes auxquels une grande quantité de mémoire virtuelle avait été allouée.

Je courais sur Linux x86-64 avec un JVM 64 bits.

2
codeDr

Étapes à exécuter .... pour résoudre l'erreur survenue lors de l'initialisation de VM Impossible de réserver suffisamment d'espace pour le tas d'objet Impossible de créer le Java machine virtuelle .

Étape 1: Réduisez la mémoire que vous utilisiez auparavant .. Java -Xms128m -Xmx512m -cp simple.jar

étape 2: Supprimez le RAM un certain temps de la carte mère, puis branchez-le et redémarrez *, il pourra libérer la mémoire de la zone de segment de blocage .. Java -Xms512m -Xmx1024m -cp simple.jar

J'espère que cela fonctionnera bien maintenant ... :-)

2
Soundar Kumar B R

Ceci est peut-être bien en dehors de la piste, mais il y a deux choses qui me viennent à l'esprit. Les deux éléments suivants supposent que vous exécutez une version 32 bits de Linux.

Il y a une limite de taille de processus sur Linux, qui semble se rappeler que sur CentOS était d'environ 2,5 Go et qui est configurée dans le noyau (c'est-à-dire un recomple à changer). Votre processus risque de ne fonctionner que lorsque vous aurez ajouté tout le code JVM + l'espace Permgen et tout le reste des bibliothèques JVM.

La deuxième chose est quelque chose que j'ai rencontré que vous pouvez être à court d'espace d'adressage, semble étrange je sais. Si vous rencontriez des difficultés pour exécuter Glassfish avec un tas de 1,5 Go, il échouait lorsque le système d'exploitation tentait de se conformer à un fichier JSP mon forking, car le système d'exploitation ne pouvait pas allouer suffisamment d'espace d'adressage pour le processus nouvellement créé, alors qu'il y avait 12 Go de mémoire dans la boîte. Il se peut que quelque chose de similaire se passe ici.

Je crains que les seules solutions aux deux solutions ci-dessus ne nécessitent une mise à niveau vers un noyau 64 bits.

J'espère que cela vous sera utile.

2
Gareth Davis

J'utilise SOA env, diminution de Xmx de 1024 à 768 dans setSOADomainENV.cmd résolu le problème.

REM set DEFAULT_MEM_ARGS=-Xms512m -Xmx1024m
set DEFAULT_MEM_ARGS=-Xms512m -Xmx768m
1
Kelvin

Etant donné qu'aucune des autres suggestions n'a fonctionné (y compris beaucoup de choses que j'aurais suggérées moi-même), pour aider à dépanner davantage, pourriez-vous essayer de courir:

sysctl -a

Sur les machines SuSE et RedHat pour voir s'il y a des différences? J'imagine que les configurations par défaut sont différentes entre ces deux distributions.

1
Jack Leow

Quelle est la machine virtuelle utilisée? Je sais que BEA JRockit ne dépasse pas 1 850 Mo pour la taille maximale du tas. Il n'échoue pas mais avertit l'utilisateur qu'il n'utilisera pas plus de 1850mB.

Je ne sais pas pourquoi il y a une telle limite, mais je sais qu'elle existe pour BEA JRockit.

Meilleures salutations.

1
Johan Guiheneuf