Utilisation de la mémoire virtuelle de Java sous Linux, trop de mémoire utilisée

259

J'ai un problème avec une application Java fonctionnant sous Linux.

Lorsque je lance l'application, en utilisant la taille de segment maximale par défaut (64 Mo), je constate qu'en utilisant l'application tops, 240 Mo de mémoire virtuelle sont alloués à l'application. Cela crée des problèmes avec certains autres logiciels de l'ordinateur, qui sont relativement limités en ressources.

La mémoire virtuelle réservée ne sera pas utilisée de toute façon, si je comprends bien, car une fois que nous atteignons la limite de tas, un OutOfMemoryErrorest lancé. J'ai exécuté la même application sous Windows et je vois que la taille de la mémoire virtuelle et la taille du tas sont similaires.

Existe-t-il de toute façon que je peux configurer la mémoire virtuelle utilisée pour un processus Java sous Linux?

Edit 1 : Le problème n'est pas le tas. Le problème est que si je définis un tas de 128 Mo, par exemple, Linux alloue toujours 210 Mo de mémoire virtuelle, ce qui n'est jamais nécessaire. **

Edit 2 : L'utilisation ulimit -vpermet de limiter la quantité de mémoire virtuelle. Si la taille définie est inférieure à 204 Mo, l'application ne s'exécutera pas même si elle n'a pas besoin de 204 Mo, seulement 64 Mo. Je veux donc comprendre pourquoi Java nécessite autant de mémoire virtuelle. Cela peut-il être changé?

Edit 3 : Il existe plusieurs autres applications en cours d'exécution dans le système, qui est intégré. Et le système a une limite de mémoire virtuelle (à partir des commentaires, des détails importants).

Mario Ortegón
la source
Pourquoi vous préoccupez-vous de l'utilisation de la mémoire virtuelle? Si vous voulez vraiment vous inquiéter, regardez l'utilisation de la mémoire résidente et lisez les commandes suivantes: free, ps, top.
basszero
2
Il existe plusieurs autres applications en cours d'exécution dans le système, qui est intégré. Et le système a une limite de mémoire virtuelle.
Mario Ortegón
ahhhh, le diable est dans les détails
basszero
Quelle implémentation de Java utilisez-vous. IIRC, le standard de tourbière (non OpenJDK) gratuit Sun JRE n'est pas autorisé pour une utilisation intégrée.
Tom Hawtin - tackline
Je pense que j'ai mal utilisé la partie "intégrée" ... elle est limitée en mémoire et le matériel est personnalisé, mais c'est toujours un ordinateur standard
Mario Ortegón

Réponses:

630

Il s'agit d'une plainte de longue date avec Java, mais elle est largement dénuée de sens, et généralement basée sur la recherche des informations erronées. Le phrasé habituel est quelque chose comme "Hello World sur Java prend 10 mégaoctets! Pourquoi a-t-il besoin de ça?" Eh bien, voici un moyen de faire Hello World sur une JVM 64 bits prétendre prendre plus de 4 gigaoctets ... au moins par une forme de mesure.

java -Xms1024m -Xmx4096m com.example.Hello

Différentes façons de mesurer la mémoire

Sous Linux, la commande top vous donne plusieurs nombres différents pour la mémoire. Voici ce qu'il dit à propos de l'exemple Hello World:

  UTILISATEUR PID PR NI VIRT RES SHR S% CPU% MEM TIME + COMMAND
 2120 kgregory 20 0 4373m 15m 7152 S 0 0,2 0: 00.10 java
  • VIRT est l'espace de mémoire virtuelle: la somme de tout dans la carte de mémoire virtuelle (voir ci-dessous). Il est largement dénué de sens, sauf lorsqu'il ne l'est pas (voir ci-dessous).
  • RES est la taille de l'ensemble résident: le nombre de pages qui résident actuellement dans la RAM. Dans presque tous les cas, c'est le seul numéro que vous devez utiliser lorsque vous dites «trop grand». Mais ce n'est toujours pas un très bon chiffre, surtout quand on parle de Java.
  • SHR est la quantité de mémoire résidente partagée avec d'autres processus. Pour un processus Java, cela est généralement limité aux bibliothèques partagées et aux fichiers JAR mappés en mémoire. Dans cet exemple, je n'avais qu'un seul processus Java en cours d'exécution, donc je soupçonne que le 7k est le résultat de bibliothèques utilisées par le système d'exploitation.
  • SWAP n'est pas activé par défaut et n'est pas affiché ici. Il indique la quantité de mémoire virtuelle qui réside actuellement sur le disque, qu'elle se trouve ou non dans l'espace d'échange . Le système d'exploitation est très bon pour conserver les pages actives dans la RAM, et les seuls remèdes pour l'échange sont (1) acheter plus de mémoire, ou (2) réduire le nombre de processus, il est donc préférable d'ignorer ce nombre.

La situation de Windows Task Manager est un peu plus compliquée. Sous Windows XP, il existe des colonnes «Utilisation de la mémoire» et «Taille de la mémoire virtuelle», mais la documentation officielle ne précise pas ce qu'elles signifient. Windows Vista et Windows 7 ajoutent plus de colonnes, et elles sont en fait documentées . Parmi celles-ci, la mesure "Working Set" est la plus utile; il correspond à peu près à la somme de RES et SHR sous Linux.

Comprendre la carte de mémoire virtuelle

La mémoire virtuelle consommée par un processus est le total de tout ce qui se trouve dans la carte de mémoire de processus. Cela inclut les données (par exemple, le tas Java), mais également toutes les bibliothèques partagées et les fichiers mappés en mémoire utilisés par le programme. Sous Linux, vous pouvez utiliser la commande pmap pour voir toutes les choses mappées dans l'espace de processus (à partir de maintenant, je ne ferai référence qu'à Linux, car c'est ce que j'utilise; je suis sûr qu'il existe des outils équivalents pour Les fenêtres). Voici un extrait de la carte mémoire du programme "Hello World"; l'ensemble de la carte mémoire comporte plus de 100 lignes, et il n'est pas rare d'avoir une liste de mille lignes.

0000000040000000 36K rx-- /usr/local/java/jdk-1.6-x64/bin/java
0000000040108000 8K rwx-- /usr/local/java/jdk-1.6-x64/bin/java
0000000040eba000 676K rwx-- [anon]
00000006fae00000 21248K rwx-- [anon]
00000006fc2c0000 62720K rwx-- [anon]
0000000700000000 699072K rwx-- [anon]
000000072aab0000 2097152K rwx-- [anon]
00000007aaab0000 349504K rwx-- [anon]
00000007c0000000 1048576K rwx-- [anon]
...
00007fa1ed00d000 1652K r-xs- /usr/local/java/jdk-1.6-x64/jre/lib/rt.jar
...
00007fa1ed1d3000 1024K rwx-- [anon]
00007fa1ed2d3000 4K ----- [anon]
00007fa1ed2d4000 1024K rwx-- [anon]
00007fa1ed3d4000 4K ----- [anon]
...
00007fa1f20d3000 164K rx-- /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
00007fa1f20fc000 1020K ----- /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
00007fa1f21fb000 28K rwx-- /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
...
00007fa1f34aa000 1576K rx-- /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3634000 2044K ----- /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3833000 16K rx-- /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3837000 4K rwx-- /lib/x86_64-linux-gnu/libc-2.13.so
...

Une explication rapide du format: chaque ligne commence par l'adresse mémoire virtuelle du segment. Ceci est suivi de la taille du segment, des autorisations et de la source du segment. Ce dernier élément est soit un fichier soit "anon", qui indique un bloc de mémoire alloué via mmap .

En partant du haut, nous avons

  • Le chargeur JVM (c'est-à-dire le programme qui s'exécute lorsque vous tapez java). C'est très petit; il ne fait que charger dans les bibliothèques partagées où le vrai code JVM est stocké.
  • Un tas de blocs anon contenant le tas Java et les données internes. Il s'agit d'une machine virtuelle Java Sun. Le tas est donc divisé en plusieurs générations, chacune étant son propre bloc de mémoire. Notez que la JVM alloue de l'espace mémoire virtuel en fonction de la -Xmxvaleur; cela lui permet d'avoir un tas contigu. La -Xmsvaleur est utilisée en interne pour indiquer la quantité de tas "en cours d'utilisation" au démarrage du programme et pour déclencher le garbage collection à l'approche de cette limite.
  • Un fichier JAR mappé en mémoire, dans ce cas le fichier qui contient les "classes JDK". Lorsque vous mappez en mémoire un fichier JAR, vous pouvez accéder aux fichiers qu'il contient de manière très efficace (au lieu de le lire chaque fois depuis le début). La JVM Sun mappe en mémoire tous les fichiers JAR du chemin de classe; si votre code d'application doit accéder à un JAR, vous pouvez également le mapper en mémoire.
  • Données par thread pour deux threads. Le bloc 1M est la pile de threads. Je n'avais pas une bonne explication pour le bloc 4k, mais @ericsoe l'a identifié comme un "bloc de garde": il n'a pas d'autorisations de lecture / écriture, donc causera une erreur de segment s'il est accédé, et la JVM le capture et le traduit à un StackOverFlowError. Pour une vraie application, vous verrez des dizaines sinon des centaines de ces entrées répétées à travers la carte mémoire.
  • L'une des bibliothèques partagées contenant le code JVM réel. Il y en a plusieurs.
  • La bibliothèque partagée pour la bibliothèque standard C. Ceci n'est qu'une des nombreuses choses que la JVM charge et qui ne font pas strictement partie de Java.

Les bibliothèques partagées sont particulièrement intéressantes: chaque bibliothèque partagée a au moins deux segments: un segment en lecture seule contenant le code de la bibliothèque et un segment en lecture-écriture qui contient des données globales par processus pour la bibliothèque (je ne sais pas ce que le segment sans autorisation est; je ne l'ai vu que sur Linux x64). La partie en lecture seule de la bibliothèque peut être partagée entre tous les processus qui utilisent la bibliothèque; par exemple, libcdispose de 1,5M d'espace de mémoire virtuelle qui peut être partagé.

Quand la taille de la mémoire virtuelle est-elle importante?

La carte de mémoire virtuelle contient beaucoup de choses. Une partie est en lecture seule, une partie est partagée et une partie est allouée mais jamais touchée (par exemple, presque tout le 4 Go de tas dans cet exemple). Mais le système d'exploitation est suffisamment intelligent pour ne charger que ce dont il a besoin, de sorte que la taille de la mémoire virtuelle est largement hors de propos.

Lorsque la taille de la mémoire virtuelle est importante, si vous utilisez un système d'exploitation 32 bits, vous ne pouvez allouer que 2 Go (ou, dans certains cas, 3 Go) d'espace d'adressage de processus. Dans ce cas, vous avez affaire à une ressource rare et devrez peut-être faire des compromis, comme réduire la taille du segment de mémoire afin de mapper en mémoire un fichier volumineux ou de créer de nombreux threads.

Mais, étant donné que les machines 64 bits sont omniprésentes, je ne pense pas qu'il faudra longtemps avant que la taille de la mémoire virtuelle ne soit une statistique complètement hors de propos.

Quand la taille définie par le résident est-elle importante?

La taille de l'ensemble résident est la partie de l'espace mémoire virtuelle qui se trouve réellement dans la RAM. Si votre RSS devient une partie importante de votre mémoire physique totale, il est peut-être temps de commencer à vous inquiéter. Si votre flux RSS prend toute votre mémoire physique et que votre système commence à échanger, il est grand temps de commencer à vous inquiéter.

Mais RSS est également trompeur, en particulier sur une machine légèrement chargée. Le système d'exploitation ne consacre pas beaucoup d'efforts à récupérer les pages utilisées par un processus. Il y a peu d'avantages à le faire, et la possibilité d'une erreur de page coûteuse si le processus touche la page à l'avenir. Par conséquent, la statistique RSS peut inclure de nombreuses pages qui ne sont pas utilisées activement.

Bottom Line

À moins que vous n'échangiez, ne vous inquiétez pas trop de ce que les différentes statistiques de la mémoire vous disent. Avec la mise en garde qu'un RSS toujours croissant peut indiquer une sorte de fuite de mémoire.

Avec un programme Java, il est beaucoup plus important de faire attention à ce qui se passe dans le tas. La quantité totale d'espace consommé est importante et vous pouvez prendre certaines mesures pour réduire cela. Plus important est le temps que vous passez dans la collecte des ordures et quelles parties du tas sont collectées.

L'accès au disque (c'est-à-dire à une base de données) coûte cher et la mémoire est bon marché. Si vous pouvez échanger l'un contre l'autre, faites-le.

kdgregory
la source
9
Vous devez tenir compte du fait que des parties de mémoire qui sont actuellement échangées sont manquantes dans la mesure RES. Vous pouvez donc avoir une valeur RES faible, mais uniquement parce que l'application était inactive et qu'une grande partie du tas a été échangée sur le disque. Java fait un très mauvais travail d'échange: sur chaque GC complet, la plupart du tas est parcouru et copié, donc si une grande partie de votre tas était en swap, le GC doit tout recharger dans la mémoire principale.
jrudolph
1
Grande réponse kdgregory! Je cours dans un environnement intégré utilisant un CF qui n'a AUCUN espace de swap. Donc, sur la base de votre réponse, toutes mes valeurs VIRT, SWAP et nFLT proviennent de fichiers mappés en mémoire ... ce qui a maintenant du sens pour mew. Savez-vous si la valeur SWAP représente des pages qui n'ont pas encore été chargées en mémoire ou des pages qui ont été échangées hors de la mémoire, ou les deux? Comment peut-on se faire une idée d'un éventuel thrashing (cartographie continue puis échange)?
Jeach
2
@Jeach - J'ai été surpris qu'un échange ait été signalé, alors j'ai démarré mon "Linux itinérant" (une clé USB avec Ubuntu 10.04 et aucun échange). Quand j'ai activé la colonne "SWAP" en haut , j'ai vu qu'Eclipse avait 509m. Lorsque je l'ai ensuite regardé avec pmap , l'espace virtuel total était de 650 m. Je soupçonne donc que le chiffre "SWAP" représente toutes les pages sur disque, pas seulement celles qui ne sont pas en mémoire.
kdgregory
2
Quant à votre deuxième question: si vous lisez constamment des pages de la carte flash, votre temps d'attente d'E / S (indiqué dans le résumé du haut comme "% wa") devrait être élevé. Attention, cependant, ce sera élevé pour n'importe quelle activité, en particulier les écritures (en supposant que votre programme en fasse).
kdgregory
1
> Le bloc 1M est une pile de threads; Je ne sais pas ce qui entre dans le bloc 4K. Le bloc 4K - qui est marqué comme n'ayant aucune autorisation de lecture ou d'écriture - est probablement un bloc de garde. En cas de dépassement de pile, cette zone est accessible, ce qui déclenche une erreur, que la JVM peut ensuite gérer en générant une Java StackOverflowException. C'est beaucoup moins cher que de vérifier le pointeur de pile à chaque appel de méthode. Les zones de garde sans autorisations définies peuvent également être utilisées dans d'autres contextes.
eriksoe
38

Il existe un problème connu avec Java et glibc> = 2.10 (inclut Ubuntu> = 10.04, RHEL> = 6).

Le remède est de fixer cet env. variable:

export MALLOC_ARENA_MAX=4

Si vous exécutez Tomcat, vous pouvez l'ajouter au TOMCAT_HOME/bin/setenv.shfichier.

Pour Docker, ajoutez ceci à Dockerfile

ENV MALLOC_ARENA_MAX=4

Il existe un article IBM sur la configuration de MALLOC_ARENA_MAX https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

Ce billet de blog dit

la mémoire résidente est connue pour se glisser d'une manière similaire à une fuite de mémoire ou à une fragmentation de la mémoire.

Il y a aussi un bug JDK ouvert JDK -8193521 "glibc gaspille de la mémoire avec la configuration par défaut"

recherchez MALLOC_ARENA_MAX sur Google ou SO pour plus de références.

Vous voudrez peut-être également régler d'autres options malloc pour optimiser la faible fragmentation de la mémoire allouée:

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
export MALLOC_ARENA_MAX=2
# disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt"
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536
Lari Hotari
la source
Cette réponse m'a vraiment aidé sur un serveur Ubuntu 64 bits avec un serveur TomEE qui a eu un peu de "consommation de mem". Le lien vers l'article IBM est vraiment une explication profonde. Merci encore pour ce bon indice!
MWiesner
1
La JVM peut entraîner une fuite de mémoire native, ce qui entraîne des symptômes similaires. Voir stackoverflow.com/a/35610063/166062 . Les instances GZIPInputStream et GZIPOutputStream non fermées peuvent également être une source de fuite.
Lari Hotari
3
Il existe un bogue JVM dans Java 8, qui entraîne une croissance illimitée de la mémoire native: bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8164293 - Si cela vous affecte, l'utilisation MALLOC_ARENA_MAXpeut ralentir la croissance de votre mémoire, mais pas résoudre entièrement le problème.
outofcoffee
@LariHotari apprécie vraiment vos efforts pour souligner la version glibc et redhat
Sam
2
Java 8u131 contient un correctif de bogue rétroporté pour le bogue JVM associé JDK-8164293 bugs.openjdk.java.net/browse/JDK-8178124 .
Lari Hotari
9

La quantité de mémoire allouée au processus Java est à peu près à la hauteur de ce à quoi je m'attendrais. J'ai rencontré des problèmes similaires en exécutant Java sur des systèmes intégrés / à mémoire limitée. L'exécution de toute application avec des limites de VM arbitraires ou sur des systèmes qui ne disposent pas de quantités suffisantes de swap a tendance à se casser. Cela semble être la nature de nombreuses applications modernes qui ne sont pas conçues pour être utilisées sur des systèmes à ressources limitées.

Vous avez quelques options supplémentaires que vous pouvez essayer de limiter l'empreinte mémoire de votre JVM. Cela pourrait réduire l'empreinte mémoire virtuelle:

-XX: ReservedCodeCacheSize = 32m Taille du cache de code réservé (en octets) - taille maximale du cache de code. [Solaris 64 bits, amd64 et -server x86: 48 m; dans 1.5.0_06 et versions antérieures, Solaris 64 bits et and64: 1024 m.]

-XX: MaxPermSize = 64m Taille de la génération permanente. [5.0 et plus récent: les machines virtuelles 64 bits sont agrandies de 30%; 1,4 amd64: 96 m; 1.3.1 -client: 32m.]

En outre, vous devez également définir votre -Xmx (taille de segment de mémoire maximale) sur une valeur aussi proche que possible de l' utilisation maximale de la mémoire réelle de votre application. Je crois que le comportement par défaut de la JVM consiste toujours à doubler la taille du segment de mémoire chaque fois qu'elle l'étend au maximum. Si vous commencez avec 32M de tas et que votre application culmine à 65M, le tas finira par croître de 32M -> 64M -> 128M.

Vous pouvez également essayer ceci pour rendre la machine virtuelle moins agressive à propos de la croissance du tas:

-XX: MinHeapFreeRatio = 40 Pourcentage minimum de tas libres après GC pour éviter l'expansion.

De plus, d'après ce que je me souviens d'avoir expérimenté cela il y a quelques années, le nombre de bibliothèques natives chargées a eu un impact énorme sur l'empreinte minimale. Le chargement de java.net.Socket a ajouté plus de 15 Mo si je me souviens bien (et je ne le fais probablement pas).

James Schek
la source
7

La JVM Sun nécessite beaucoup de mémoire pour HotSpot et elle est mappée dans les bibliothèques d'exécution en mémoire partagée.

Si la mémoire est un problème, envisagez d'utiliser une autre machine virtuelle Java appropriée pour l'incorporation. IBM a j9, et il y a le "jamvm" Open Source qui utilise les bibliothèques de chemin de classe GNU. Sun a également la JVM Squeak en cours d'exécution sur les SunSPOTS, il existe donc des alternatives.

Thorbjørn Ravn Andersen
la source
Est-ce une option pour désactiver le hot spot?
Mario Ortegón
Peut-être. Vérifiez les options de ligne de commande pour la machine virtuelle Java que vous utilisez.
Thorbjørn Ravn Andersen
3

Juste une pensée, mais vous pouvez vérifier l'influence d' une ulimit -voption .

Ce n'est pas une solution réelle car cela limiterait l'espace d'adressage disponible pour tous les processus, mais cela vous permettrait de vérifier le comportement de votre application avec une mémoire virtuelle limitée.

VonC
la source
C'est exactement mon problème. Mon tas est réglé sur 64 Mo, mais Linux réserve 204 Mo. Si je place l'ulimit en dessous de 204, l'application ne s'exécute pas du tout.
Mario Ortegón
Intéressant: la définition de ulimit peut avoir des effets secondaires imprévus pour d'autres processus, expliquant pourquoi l'application ne peut pas s'exécuter.
VonC
Le problème semble être que Java nécessite de réserver cette plus grande quantité de mémoire virtuelle même s'il ne l'utilisera pas. Sous Windows, la mémoire virtuelle utilisée et le paramètre Xmx sont plus proches.
Mario Ortegón
L'avez-vous essayé avec une JVM JRockit?
VonC
Étant donné que l'allocation de mémoire de la machine virtuelle Java est la somme de l'allocation de tas et de la taille de perm (la première peut être fixée à l'aide des options -Xms et -Xmx), avez-vous essayé certains paramètres avec -XX: PermSize et -XX: MaxPermSize (par défaut de 32 Mo à 64 Mo selon la version JVM)?
VonC
3

Une façon de réduire le segment de mémoire d'un système avec des ressources limitées peut être de jouer avec la variable -XX: MaxHeapFreeRatio. Il est généralement défini sur 70 et correspond au pourcentage maximal du segment de mémoire libre avant que le GC ne le rétrécisse. En le réglant sur une valeur inférieure, et vous verrez par exemple dans le profileur jvisualvm qu'un plus petit segment de tas est généralement utilisé pour votre programme.

EDIT: pour définir de petites valeurs pour -XX: MaxHeapFreeRatio, vous devez également définir -XX: MinHeapFreeRatio Par exemple

java -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=25 HelloWorld

EDIT2: Ajout d'un exemple pour une application réelle qui démarre et effectue la même tâche, une avec des paramètres par défaut et une avec 10 et 25 comme paramètres. Je n'ai pas remarqué de réelle différence de vitesse, bien que java devrait en théorie utiliser plus de temps pour augmenter le tas dans le dernier exemple.

Paramètres par défaut

À la fin, le tas maximum est 905, le tas utilisé est 378

MinHeap 10, MaxHeap 25

À la fin, le tas max est 722, le tas utilisé est 378

Cela a en fait un certain impact, car notre application s'exécute sur un serveur de bureau distant et de nombreux utilisateurs peuvent l'exécuter en même temps.

runholen
la source
1

Java 1.4 de Sun a les arguments suivants pour contrôler la taille de la mémoire:

-Xmsn Spécifiez la taille initiale, en octets, du pool d'allocation de mémoire. Cette valeur doit être un multiple de 1024 supérieur à 1 Mo. Ajoutez la lettre k ou K pour indiquer les kilo-octets, ou m ou M pour indiquer les mégaoctets. La valeur par défaut est 2 Mo. Exemples:

           -Xms6291456
           -Xms6144k
           -Xms6m

-Xmxn Spécifiez la taille maximale, en octets, du pool d'allocation de mémoire. Cette valeur doit être un multiple de 1024 supérieur à 2 Mo. Ajoutez la lettre k ou K pour indiquer les kilo-octets, ou m ou M pour indiquer les mégaoctets. La valeur par défaut est 64 Mo. Exemples:

           -Xmx83886080
           -Xmx81920k
           -Xmx80m

http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/java.html

Java 5 et 6 en ont plus. Voir http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp

Paul Tomblin
la source
1
Le problème que j'ai n'est pas avec la taille du tas, mais avec la quantité de mémoire virtuelle attribuée par Linux
Mario Ortegón
Lisez l'explication de kdgregory. La réduction de la taille du tas, de la "nouvelle taille" et des autres paramètres configurables réduira la quantité de mémoire VRAIE que prend le jvm.
Paul Tomblin
Il peut avoir un problème légitime. Certaines applications (comme celle que j'ai écrite) mappent un fichier de 1 Go et certains systèmes ne disposent que de 2 Go de mémoire virtuelle, dont certains sont remplis de bibliothèques partagées. Et si tel est le problème, il doit définitivement désactiver la randomisation DSO. Il existe une option dans / proc.
Zan Lynx
0

Non, vous ne pouvez pas configurer la quantité de mémoire requise par VM. Cependant, notez qu'il s'agit de mémoire virtuelle, non résidente, donc elle y reste sans danger si elle n'est pas réellement utilisée.

Alternativement, vous pouvez essayer une autre JVM puis une Sun, avec une empreinte mémoire plus petite, mais je ne peux pas vous conseiller ici.

Marko
la source