Il y a certaines choses à propos des piles de fils que l'équipe du Spécification Java nous dit. Entre autres choses :
-
Chaque thread de la machine virtuelle Java possède une pile privée de la machine virtuelle Java, créée en même temps que le thread.
-
Étant donné que la pile de la machine virtuelle Java n'est jamais manipulée directement, sauf pour pousser et extraire des cadres, les cadres peuvent être alloués au tas. La mémoire de la pile de la machine virtuelle Java n'a pas besoin d'être contiguë.
-
La spécification permet aux piles de la machine virtuelle Java d'avoir une taille fixe ou de s'étendre et se contracter dynamiquement selon les besoins du calcul.
Maintenant, si nous nous concentrons sur les implémentations de la JVM telles que HotSpot, nous pouvons obtenir quelques informations supplémentaires. Voici quelques faits que j'ai recueillis auprès de différentes sources :
- La taille minimale de la pile dans HotSpot pour un thread semble être fixée. C'est ce que le
-Xss
l'option est pour. (Source)
Dans Java SE 6, la valeur par défaut sur Sparc est de 512k dans la VM 32 bits, et de 1024k dans la VM 64 bits. ... Vous pouvez réduire la taille de votre pile en l'exécutant avec l'option -Xss. ... 64k est la quantité minimale d'espace de pile autorisée par thread.
- JRockit alloue une mémoire séparée du tas où se trouvent les piles. (Source)
Notez que la JVM utilise plus de mémoire que le simple tas. Par exemple, les méthodes Java, les piles de threads et les handles natifs sont alloués dans une mémoire distincte du tas, tout comme les structures de données internes de la JVM.
-
Il existe une correspondance directe entre un Thread Java et un Thread OS natif dans HotSpot. (Source) .
-
Mais la pile de fils Java dans HotSpot est gérée par le logiciel, ce n'est pas une pile de fils native du système d'exploitation. (Source)
Elle utilise une pile logicielle distincte pour transmettre les arguments Java, tandis que la pile C native est utilisée par la VM elle-même. Un certain nombre de variables internes de la JVM, telles que le compteur de programme ou le pointeur de pile pour un thread Java, sont stockées dans des variables C, dont il n'est pas garanti qu'elles soient toujours conservées dans les registres matériels. La gestion de ces structures de l'interpréteur logiciel consomme une part considérable du temps d'exécution total.
-
La JVM utilise également la même pile de threads Java pour les méthodes natives et les appels au runtime de la JVM (par exemple, le chargement des classes). (Source) .
-
Il est intéressant de noter que même les objets alloués peuvent parfois être situés sur la pile au lieu du tas pour optimiser les performances. (Source)
Les JVM peuvent utiliser une technique appelée "escape analysis", qui leur permet de savoir que certains objets restent confinés à un seul thread pendant toute leur durée de vie, et que cette durée est limitée par la durée de vie d'un cadre de pile donné. Ces objets peuvent être alloués en toute sécurité sur la pile plutôt que sur le tas.
Et parce qu'une image vaut mille mots, en voici une tirée de James Bloom
Je réponds maintenant à certaines de vos questions :
Comment la JVM sait-elle combien de threads seront créés ?
Ce n'est pas le cas. Peut être facilement prouvé par contradiction en créant un nombre variable de fils. Il fait quelques hypothèses sur le nombre maximal de fils et la taille de la pile de chaque fil. C'est pourquoi vous risquez de manquer de mémoire (et non de mémoire de tas !) si vous allouez trop de threads.
Java crée-t-il une pile pour chaque thread lors de sa création ?
Comme mentionné précédemment, chaque thread de la machine virtuelle Java possède une pile privée de la machine virtuelle Java, créée en même temps que le thread. (Source) .
Si oui, où se trouve exactement la pile sur la mémoire ? Elle ne se trouve certainement pas dans le tas "géré".
Comme indiqué ci-dessus, Spécification Java permet à la mémoire de la pile d'être stockée sur le tas, techniquement parlant. Mais au moins la JVM de JRockit utilise une partie différente de la mémoire.
La JVM crée-t-elle la pile à partir de la mémoire native ou pré-alloue-t-elle une section de la zone mémoire gérée pour la pile ?
La pile est gérée par la JVM car la spécification Java prescrit comment il doit se comporter : Une pile de la machine virtuelle Java stocke les trames (§2.6). Une pile de la Machine Virtuelle Java est analogue à la pile d'un langage conventionnel . Une exception : les piles de méthodes natives utilisées pour native
méthodes. Plus d'informations à ce sujet dans la spécification .