Mémoire maximale Java sous Windows XP

103

J'ai toujours pu allouer 1400 mégaoctets pour Java SE fonctionnant sous Windows XP 32 bits (Java 1.4, 1.5 et 1.6).

java -Xmx1400m ...

Aujourd'hui, j'ai essayé la même option sur une nouvelle machine Windows XP utilisant Java 1.5_16 et 1.6.0_07 et j'ai obtenu l'erreur:

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

Par essais et erreurs, il semble que 1200 mégaoctets soient le maximum que je puisse allouer à cette machine.

Des idées pourquoi une machine autoriserait 1400 et une autre seulement 1200?

Edit: La machine dispose de 4 Go de RAM avec environ 3,5 Go que Windows peut reconnaître.

Steve Kuo
la source
Vous remarquerez une différence dans le maximum entre l'exécution de l'application dans un shell 32 bits ou un shell 64 bits, du moins d'après mon expérience, bien que les systèmes WindowsXP 64 bits soient rares.
djangofan du

Réponses:

124

Gardez à l'esprit que Windows dispose d'une gestion de la mémoire virtuelle et que la machine virtuelle Java n'a besoin que de la mémoire contiguë dans son espace d'adressage . Ainsi, les autres programmes exécutés sur le système ne devraient pas nécessairement avoir un impact sur la taille de votre tas. Ce qui vous gênera, ce sont les DLL qui sont chargées dans votre espace d'adressage. Malheureusement, les optimisations dans Windows qui minimisent le déplacement des DLL pendant la liaison font qu'il est plus probable que vous ayez un espace d'adressage fragmenté. Outre les éléments habituels, les éléments susceptibles de réduire votre espace d'adressage incluent les logiciels de sécurité, les logiciels CBT, les logiciels espions et d'autres formes de logiciels malveillants. Les causes probables des écarts sont les différents correctifs de sécurité, les versions d'exécution C, etc. Les pilotes de périphérique et les autres bits du noyau ont leur propre espace d'adressage (les 2 Go restants de l'espace de 4 Go de 32 bits).

Vous pouvez essayer de parcourir vos liaisons DLL dans votre processus JVM et essayer de rebaser vos DLL dans un espace d'adressage plus compact. Pas amusant, mais si vous êtes désespéré ...

Alternativement, vous pouvez simplement passer à Windows 64 bits et à une JVM 64 bits. Malgré ce que d'autres ont suggéré, même si cela consommera plus de RAM, vous aurez un espace d'adressage virtuel beaucoup plus contigu, et allouer 2 Go de manière contiguë serait trivial.

Christopher Smith
la source
5
Utilisez Process Explorer pour voir où dans la mémoire les DLL sont chargées. Souvent, un pilote mis à jour se collera au milieu de votre espace d'adressage. En utilisant la commande REBASE, vous pouvez facilement les écarter. Gardez à l'esprit que la DLL est sujette à être mise à jour à nouveau et à casser des choses.
brianegge le
2
Je n'ai jamais accepté cela comme une réponse et pourtant stackoverflow l'a marqué comme répondu.
Steve Kuo
@Christopher, Est-il possible d'utiliser une JVM 64 bits sur un Windows XP 32 bits?
Pacerier
@Pacerier Désolé, j'ai manqué votre requête. AFAIK, ce n'est pas possible. OS X avait quelques astuces pour l'espace utilisateur 64 bits avec des noyaux 32 bits, mais je n'ai jamais entendu parler de telle chose pour Windows.
Christopher Smith
@ChristopherSmith, Btw, vous avez mentionné "les autres programmes exécutés sur le système ne devraient pas nécessairement avoir un impact sur la taille de votre tas ". Si oui, comment expliquer ce résultat: stackoverflow.com/questions/9303889/... ?
Pacerier
50

Cela a à voir avec la mémoire contiguë.

Voici quelques informations que j'ai trouvées en ligne pour quelqu'un qui me le demandait auparavant, soi-disant d'un "dieu VM":

La raison pour laquelle nous avons besoin d'une région mémoire contiguë pour le tas est que nous avons un tas de structures de données secondaires qui sont indexées par des décalages (mis à l'échelle) à partir du début du tas. Par exemple, nous suivons les mises à jour de référence d'objet avec un "tableau de marque de carte" qui a un octet pour chaque 512 octets de tas. Lorsque nous stockons une référence dans le tas, nous devons marquer l'octet correspondant dans le tableau de marque de carte. Nous décalons à droite l'adresse de destination du magasin et l'utilisons pour indexer le tableau de marques de carte. Jeux d'arithmétique amusants que vous ne pouvez pas faire en Java et auxquels vous (devez :-) jouer en C ++.

Habituellement, nous n'avons pas de problème pour obtenir des régions contiguës modestes (jusqu'à environ 1,5 Go sur Windohs, jusqu'à environ 3,8 Go sur Solaris. YMMV.). Sur Windohs, le problème est principalement qu'il y a des bibliothèques qui sont chargées avant le démarrage de la JVM et qui divisent l'espace d'adressage. L'utilisation du commutateur / 3GB ne rebasera pas ces bibliothèques, elles restent donc un problème pour nous.

Nous savons comment créer des tas de blocs, mais leur utilisation entraînerait des frais généraux. Nous avons plus de demandes pour une gestion du stockage plus rapide que pour des tas plus volumineux dans la JVM 32 bits. Si vous voulez vraiment de gros tas, passez à la JVM 64 bits. Nous avons toujours besoin d'une mémoire contiguë, mais il est beaucoup plus facile d'accéder à un espace d'adressage 64 bits.

Uri
la source
C'est très intéressant. Je me suis toujours demandé pourquoi 1500 Mo, maintenant je l'ai, merci!
Tim Büthe
3
Désolé pour le suivi d'une question ancienne, mais c'est la meilleure réponse que j'ai vue jusqu'à présent. Mais pourquoi la JVM échoue-t-elle au démarrage si elle ne parvient pas à obtenir la taille maximale du tas? Ne devrait-il pas se contenter tranquillement de la meilleure taille au-dessus du minimum ?
Stroboskop
19

Les limites de taille du tas Java pour Windows sont:

  • taille maximale de tas possible sur Java 32 bits: 1,8 Go
  • limite de taille de tas recommandée sur Java 32 bits: 1,5 Go (ou 1,8 Go avec l'option / 3 Go)

Cela ne vous aide pas à obtenir un plus gros tas Java, mais vous savez maintenant que vous ne pouvez pas aller au-delà de ces valeurs.

MicSim
la source
10

Oracle JRockit , qui peut gérer un tas non contigu, peut avoir une taille de tas Java de 2,85 Go sous Windows 2003 / XP avec le commutateur / 3GB. Il semble que la fragmentation puisse avoir un impact considérable sur la taille d'un tas Java.

Kire Haglin
la source
6

La JVM a besoin de mémoire contiguë et en fonction de ce qui est en cours d'exécution, de ce qui était en cours d'exécution auparavant et de la façon dont Windows a géré la mémoire, vous pourrez peut-être obtenir jusqu'à 1,4 Go de mémoire contiguë. Je pense que Windows 64 bits permettra des tas plus grands.

James AN Stauffer
la source
2
Je pense que le système d'exploitation moderne émule la mémoire continue pour le. Depuis le 80486, l'architecture x86 prend en charge la pagination pour faciliter la réorganisation de la mémoire physique.
Mnementh le
3
Mnemeth: Premièrement, il existe une API spécifique (AllocateUserPhysicalPages) dans WINAPI pour les outils avancés tels que les bases de données et les machines virtuelles qui sont mieux à même de gérer eux-mêmes leur mémoire avec Windows à l'écart. Deuxièmement, la pagination est une fonction de mode protégé 80386, et non 80486.
Tamas Czinege
6

La JVM de Sun a besoin de mémoire contiguë. Ainsi, la quantité maximale de mémoire disponible est dictée par la fragmentation de la mémoire. En particulier, les DLL du pilote ont tendance à fragmenter la mémoire lors du chargement dans une adresse de base prédéfinie. Votre matériel et ses pilotes déterminent donc la quantité de mémoire que vous pouvez obtenir.

Deux sources pour cela avec des déclarations d'ingénieurs Sun: blog du forum

Peut-être une autre JVM? Avez-vous essayé Harmony ? Je pense qu'ils ont prévu d'autoriser la mémoire non continue.

le canard
la source
Mais j'ai pu allouer 1300 Mo sur une machine avec seulement 1 Go de RAM (plus mémoire virtuelle). Ma machine de 2 Go de RAM (également avec mémoire virtuelle) ne peut allouer que 1200 Mo.
Steve Kuo
L'harmonie est morte, n'est-ce pas?
Pacerier
Oui: "Apache Harmony a pris sa retraite à l'Apache Software Foundation depuis le 16 novembre 2011."
bobbel
3

Je pense que cela a plus à voir avec la façon dont Windows est configuré comme l' indique cette réponse: Option Java -Xmx

Quelques tests supplémentaires: j'ai pu allouer 1300 Mo sur une ancienne machine Windows XP avec seulement 768 Mo de RAM physique (plus la mémoire virtuelle). Sur ma machine de 2 Go de RAM, je ne peux obtenir que 1220 Mo. Sur diverses autres machines d'entreprise (avec Windows XP plus ancien), j'ai pu obtenir 1400 Mo. La machine avec une limite de 1220 Mo est assez nouvelle (vient d'être achetée chez Dell), donc peut-être qu'elle a des Windows et des DLL plus récents (et plus gonflés) (il exécute Windows XP Pro Version 2002 SP2).

Steve Kuo
la source
Cela pourrait également être affecté par vos paramètres de mémoire virtuelle.
skaffman
Toutes les machines avec lesquelles je teste ont une mémoire virtuelle au moins deux fois supérieure à celle de la RAM physique.
Steve Kuo
notez que vous ne voulez vraiment jamais vraiment utiliser la mémoire virtuelle avec java, car les performances du GC deviendront très mauvaises. La quantité de mémoire dépend des DLL qui ont déjà été chargées et qui ont fragmenté la mémoire.
kohlerm
2

J'ai reçu ce message d'erreur lors de l'exécution d'un programme java à partir d'un VPS virtuozzo (mémoire limitée). Je n'avais spécifié aucun argument de mémoire et j'ai trouvé que je devais définir explicitement une petite quantité car la valeur par défaut devait être trop élevée. Par exemple -Xmx32m (doit évidemment être réglé en fonction du programme que vous exécutez).

Il suffit de mettre ceci ici au cas où quelqu'un d'autre obtiendrait le message d'erreur ci-dessus sans spécifier une grande quantité de mémoire comme l'a fait l'interrogateur.

William Denniss
la source
1

Le JDK / JRE de sun a besoin d'une quantité contiguë de mémoire si vous allouez un bloc énorme.

Le système d'exploitation et les applications initiales ont tendance à allouer des bits et des morceaux lors du chargement, ce qui fragmente la RAM disponible. Si un bloc contigu n'est PAS disponible, le JDK SUN ne peut pas l'utiliser. JRockit de Bea (acquis par Oracle) peut allouer de la mémoire à partir de pièces.

Anjanb
la source
1

Tout le monde semble répondre à propos de la mémoire contiguë, mais a négligé de reconnaître un problème plus pressant.

Même avec une allocation de mémoire contiguë à 100%, vous ne pouvez pas avoir une taille de tas de 2 Gio sur un système d'exploitation Windows 32 bits (* par défaut). Cela est dû au fait que les processus Windows 32 bits ne peuvent pas adresser plus de 2 Gio d'espace.

Le processus Java contiendra perm gen (avant Java 8), la taille de la pile par thread, la surcharge de la JVM / bibliothèque (qui augmente sensiblement à chaque construction) en plus du tas .

De plus, les indicateurs JVM et leurs valeurs par défaut changent entre les versions. Exécutez simplement ce qui suit et vous aurez une idée:

 java -XX:+PrintFlagsFinal

De nombreuses options affectent la division de la mémoire dans et hors du tas. Vous laissant avec plus ou moins de ces 2 Gio pour jouer ...

Pour réutiliser des portions de cette réponse à moi (sur Tomcat, mais applique à tout processus Java):

Le système d'exploitation Windows limite l'allocation de mémoire d'un processus 32 bits à 2 Gio au total (par défaut).

[Vous ne pourrez] allouer qu'environ 1,5 Gio d'espace de mémoire car il y a aussi une autre mémoire allouée au processus (la surcharge JVM / bibliothèque, l'espace perm gen, etc.).

Pourquoi Windows 32 bits impose-t-il une limite d'espace d'adressage de processus de 2 Go, alors que Windows 64 bits impose une limite de 4 Go?

D'autres systèmes d'exploitation modernes [cough Linux] permettent aux processus 32 bits d'utiliser la totalité (ou la plupart) de l'espace adressable de 4 Gio.

Cela dit, les systèmes d'exploitation Windows 64 bits peuvent être configurés pour augmenter la limite des processus 32 bits à 4 Gio (3 Gio sur 32 bits):

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366778(v=vs.85).aspx

Michael
la source
1
Cette réponse explique uniquement pourquoi il ne pourrait allouer que 2 Go, pas pourquoi il peut allouer 1,4 Go sur un ordinateur et seulement 1,2 Go sur un autre. Il n'atteint ni vos limites de 1,5 Go, 2 Go ou 4 Go indiquées ici.
vapcguy
1
Le paragraphe sur les indicateurs JVM explique en partie pourquoi la mémoire peut varier entre les versions. Notez également que le paramètre de tas est toujours une (grande) fraction de la taille totale du processus - donc un paramètre ci-dessous qui peut toujours atteindre la limite de processus de 2 Gio - un autre peut être limité par une allocation de mémoire contiguë.
Michael
Ou peut-être la limite de 1,5 Go, sur cette allocation de 1,4 Go qu'il fait. Cela a plus de sens maintenant - merci pour cette clarification.
vapcguy
0

Voici comment augmenter la taille de la pagination

  1. clic droit sur mon ordinateur ---> propriétés ---> Avancé
  2. dans la section des performances, cliquez sur les paramètres
  3. cliquez sur l'onglet Avancé
  4. dans la section Mémoire virtuelle, cliquez sur modifier. Il affichera votre taille de pagination actuelle.
  5. Sélectionnez Disque où l'espace disque dur est disponible.
  6. Fournissez la taille initiale et la taille maximale ... par exemple, la taille initiale 0 Mo et la taille maximale 4000 Mo. (Autant que vous en aurez besoin)
Israël Margulies
la source
0

** Il existe de nombreuses façons de modifier la taille du tas comme,

  1. file-> setting-> build, exceution, deployment-> compilateur ici, vous trouverez la taille du tas
  2. file-> setting-> build, exceution, deployment-> compiler-> andriod ici aussi, vous trouverez la taille du tas. Vous pouvez le référer pour le projet andriod si vous rencontrez le même problème.

Ce qui a fonctionné pour moi était

  1. Définissez le chemin JAVA_HOME approprié au cas où java serait mis à jour.

  2. créer une nouvelle variable système ordinateur-> propriétés-> paramètre avancé- > créer une nouvelle variable système

nom: _JAVA_OPTION valeur: -Xmx750m

FYI: vous pouvez trouver l'option VM par défaut dans l'aide d'Intellij- > modifier l'option de machine virtuelle personnalisée , dans ce fichier, vous voyez la taille minimale et maximale du tas. **

Akanksha gore
la source
-1

Premièrement, utiliser un fichier d'échange lorsque vous avez 4 Go de RAM est inutile. Windows ne peut pas accéder à plus de 4 Go (en fait, moins à cause des trous de mémoire), le fichier d'échange n'est donc pas utilisé.

Deuxièmement, l'espace d'adressage est divisé en 2, moitié pour le noyau, moitié pour le mode utilisateur. Si vous avez besoin de plus de RAM pour vos applications, utilisez l'option / 3GB dans boot.ini (assurez-vous que java.exe est marqué comme "grande adresse consciente" (google pour plus d'informations).

Troisièmement, je pense que vous ne pouvez pas allouer les 2 Go complets d'espace d'adressage car java gaspille de la mémoire en interne (pour les threads, le compilateur JIT, l'initialisation de la VM, etc.). Utilisez le commutateur / 3GB pour en savoir plus.

user17544
la source
1
L'idée d'un fichier d'échange inutile avec 4 Go ou RAM est fausse. Sans un fichier d'échange, le système d'exploitation ne peut pas expulser les données de processus inutilisées (espace de pile pour les services inutilisés, etc.) de la RAM physique, réduisant ainsi la quantité de RAM disponible pour le travail réel. Avoir un fichier d'échange libère de la RAM.
personne le