Je n'ai pas travaillé avec des VM de qualité production, mais voici mes cinq centimes.
.text
dans les exécutables Unix appartiennent à la section fichier qui stocke le code exécutable ; au moment de l'exécution, cette section de fichier est mappée sur une zone de mémoire allouée par l'éditeur de liens du système lors de l'initialisation du programme, c'est tout (sous Linux, vous pouvez voir la disposition des sections en mémoire dans le fichier /proc/$PID/maps
).
En ce qui concerne la compilation JIT sur les systèmes de type Unix, je ne peux penser qu'aux zones de mémoire qui ont été attribuées par mmap
appel système con PROT_EXEC
activé. Cet appel est spécifié par les standards POSIX et utilisé par l'éditeur de liens système de Linux, ld.so
pour charger en mémoire tout fichier exécutable natif. Cet appel peut également être utilisé pour allouer de nouvelles zones de mémoire exécutable au moment de l'exécution.
Le tas habituel est souvent protégé par les OS/ MMU d'être exécuté, comme tout /proc/$PID/maps
suggère :
00dd4000-01292000 rw-p 00000000 00:00 0 [heap]
aquí rw-p
signifie qu'aucune donnée dans [heap]
peuvent être exécutées (bien que, par exemple, ce ne soit pas le cas des CPU x86 32 bits sans PAE, ils n'ont pas la capacité matérielle d'empêcher l'exécution de certaines données de la mémoire en tant que code), mais peuvent être lues/écrites.
Une VM a donc besoin d'une zone de mémoire dédiée avec une autorisation d'exécution de code. En effet, cherchons rwx
des zones de mémoire dans la disposition de la mémoire d'un processus java :
# cat /proc/12929/maps | grep rwx # I run a Java VM with PID 12929
f3700000-f3940000 rwxp 00000000 00:00 0 # - an unnamed executable & writable region
L'exécution du code natif consiste alors à assembler le code natif compilé par JIT, soit indépendamment de la position (comme le code des objets partagés est compilé, avec gcc
option -fPIC
) ou en utilisant l'adresse renvoyée par mmap()
.