2011-01-03 4 views
4

Avec les options et -Xmx, il est possible de définir la taille initiale et maximale du pool d'allocation de mémoire. En utilisant strace/truss sous Linux et AIX, j'ai découvert que la JVM utilise en interne l'appel système (k) mmap. L'adresse -Parameter étant NULL, le système d'exploitation décide à quelle adresse de mémoire virtuelle il mappe la mémoire.Spécifier l'adresse du pool d'allocation de mémoire Java

$ truss java -Xmx512M Hello 2>&1 | grep mmap 
kmmap(0x00000000, 536870912, 3, 17, -1, 0x00000000, 0x00000000) = 0xB0000000 

Est-il possible de spécifier cette adresse? Contexte: Je dois appeler du code hérité via l'interface JNI (Java Native Interface), qui nécessite d'énormes quantités de données non relocalisables (2 Go dans un espace d'adressage 32 bits) mappées à un emplacement spécifique en mémoire. Cette région chevauche l'emplacement du pool d'allocation de mémoire Javas.

Edit: Ceci est la mise en page de la mémoire réelle:

0x0... AIX 
0x1... Text 
0x2... Stack 
0x3... Heap 
0x4... Heap 
...... Legacy Data (2 GB) 
0xd... Shared Library Text 
0xe... unused 
0xf... Shared Library Data 

Mon but est de déplacer le Java pool d'allocation mémoire de 0xb/0xc dans les segments 0x3/de 0x4, ce qui est également disponible dans la norme (non grand) modèle de mémoire.

+0

Pouvez-vous modifier le code existant pour rendre son emplacement de mémoire configurable? –

+0

«qui exige d'énormes quantités» toute estimation en mb ou gb? – Favonius

Répondre

2

Vous pourriez peut-être inverser ce problème. Démarrer un processus natif et faire ce que vous devez faire pour réserver votre espace non-négociable (mmap ou autre). Ensuite, utilisez le invocation API de Java pour créer et démarrer une JVM dans votre processus natif. Je ne trouve pas de documentation sur la façon dont cette machine virtuelle fait sa gestion de la mémoire, mais it stands to reason qu'elle fonctionnera bien avec la mémoire qui a déjà été allouée par le processus hôte (j'imagine qu'elle utilise simplement le malloc local), donc elle trouvera ailleurs pour mettre son tas. Si vous laissez la région 0x3-0x4 non allouée, vous pouvez espérer qu'elle sera mise là.

Cependant, je pense qu'il existe un risque réel qu'il n'y ait plus assez d'espace d'adressage dans votre modèle de mémoire pour une machine virtuelle Java. La région 0x3-0x4 est, quoi, 512 Mo? Si vous pouvez installer une JVM entière (tas, pile, perm, structures VM, etc), alors bien, mais sinon, vous pouvez constater que lorsque la JVM ne peut pas allouer de mémoire contiguë pour le tas, elle devient très bouleversée . Ou peut-être pas. Je ne sais vraiment pas.

Donc, après avoir suggéré cela, je vous recommande fortement de ne pas le faire, et de suivre à la place sleske's advice et de mettre le code natif dans un processus séparé.

+0

Super, cela a fonctionné. – Frank

+0

@Frank: bonne chance! –

+0

En utilisant l'API Java Invocation proposée, j'ai un prototype C++ fonctionnel. Dans le petit modèle de mémoire, AIX place stack et heap dans le segment 0x2. Le prototype cartographie ensuite 2 Go en commençant par le segment 0x5. Enfin, il crée une JVM et appelle la méthode principale, ne laissant que le segment 0x3 pour Java. Et oui, je suis absolument conscient que c'est très spécifique à la plate-forme, non portable, dangereux et laid, mais c'est un premier pas loin de la poignée de fer de Corba. Yay. – Frank

2

Personnellement, je n'ai jamais entendu parler d'un moyen de configurer l'adresse du pool d'allocation. S'il y a un tel paramètre, c'est probablement très obscur. La seule façon d'être sûr est de regarder la source du JDK/JRE, disponible à http://hg.openjdk.java.net/. Si le paramètre NULL est codé en dur, vous n'avez pas de chance.

Pour une solution de rechange, si vous ne pouvez pas fixer le code natif conduisant mal:

Vous pouvez écrire un petit programme natif d'appeler votre code natif, puis appeler le programme à partir de Java (via Runtime.exec). De cette façon, le code vilain obtient son propre processus d'exploitation avec des adresses séparées. Bien sûr, ce n'est faisable que s'il n'y a pas trop de va-et-vient entre le code natif et Java.

Ou faire le code dans un petit serveur qui fonctionne en parallèle à votre application Java, de sorte que les deux peuvent communiquer ...

Note complémentaire:

Je viens de remarquer dans la page de mmap qui donne une adresse à mmap est pas nécessairement pris en charge:

MAP_FIXED: Interprétez adr exactement. [...] Il est défini dans l'implémentation si MAP_FIXED doit être pris en charge. MAP_FIXED doit être pris en charge sur les systèmes conformes XSI . [...] Lorsque MAP_FIXED n'est pas défini, l'implémentation utilise addr d'une manière définie par l'implémentation pour parvenir à .

http://linux.die.net/man/3/mmap

Donc, même si vous parvenez à laisser l'appel machine virtuelle Java mmap avec une certaine adresse, qui peut toujours pas réussir.

+0

Merci pour l'indice du code source. Peut-être que nous devons compiler notre propre exécutable Java. Mais je préférerais éviter cela. Je n'ai pas pu localiser le fichier * right * mmap à partir de hotspot/src/os/linux/lanceur/java.c – Frank

+0

Le code existant semble fou. Enchevêtrons son propre processus afin qu'il puisse faire ses propres trucs fous, avec un petit encapsuleur qui vous permet d'envoyer des requêtes à son entrée standard, et obtenir des réponses de sa sortie standard. Si vous essayez cela et que ce n'est pas assez rapide, communiquez avec lui en utilisant la mémoire partagée - allouer un ByteBuffer direct du côté java, puis utiliser un peu de JNI pour configurer le mapping partagé. Partagez cette correspondance dans le processus de code hérité. –

+0

@Tom: L'astuce de la mémoire partagée semble être une bonne idée; Je n'y ai pas pensé quand j'ai proposé de mettre le code dans un processus qui lui soit propre. – sleske

1

Une idée que vous pouvez essayer est d'utiliser un LD_PRELOAD pour injecter votre propre comportement kmmap. Google fournit un exemple de LD_PRELOAD pour injecter un malloc personnalisé dans le projet TCMalloc.

+0

Les deux, vos idées et Toms sonnent vraiment bien pour moi. Je vais essayer les deux, quand je suis de retour au travail, omg, 8 heures. Ecrire un (heureusement) serveur sain n'est pas (encore) possible, j'en ai peur. Merci pour les bons conseils et ... bonne nuit ;-) – Frank

+0

Cela ressemble à une solution hackish et dangereuse. OTOH, c'est un problème dangereux et hackish, donc, malheureusement, c'est probablement approprié: - /. – sleske

Questions connexes