Il y a quelques choses sur les piles de threads que la spécification Java nous dit. Entre autres :
-
Chaque thread de la machine virtuelle Java a une pile privée de la machine virtuelle Java, créée en même temps que le thread.
-
Parce que la pile de la machine virtuelle Java n'est jamais manipulée directement sauf pour pousser et retirer des cadres, les cadres peuvent être alloués en tas. La mémoire pour une pile de la machine virtuelle Java n'a pas besoin d'être contiguë.
-
La spécification autorise les piles de la machine virtuelle Java à être de taille fixe ou à s'étendre et se contracter dynamiquement selon les besoins du calcul.
Maintenant, si nous nous concentrons sur les implémentations JVM telles que HotSpot, nous pouvons obtenir plus d'informations. Voici quelques faits que j'ai collectés auprès de différentes sources :
- La taille minimale de la pile dans HotSpot pour un thread semble être fixe. C'est pour cela que l'option
-Xss
mentionnée est utilisée. (Source)
Dans Java SE 6, le 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 exécutant avec l'option -Xss. ... 64k est la quantité minimale d'espace de pile autorisée par thread.
- JRockit alloue de la mémoire séparément de la pile où les piles sont situées. (Source)
Remarquez que la JVM utilise plus de mémoire que simplement le tas. Par exemple, les méthodes Java, les piles de threads et les poignées natives sont allouées dans une mémoire distincte du tas, ainsi que 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 threads Java dans HotSpot est gérée par logiciel, ce n'est pas une pile de threads native OS. (Source)
Il utilise une pile de logiciel distincte pour passer 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, qui ne sont pas garanties d'être toujours conservées dans les registres matériels. La gestion de ces structures d'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 d'exécution de la JVM (par exemple le chargement de classe). (Source).
-
Intéressant, même les objets alloués peuvent parfois être situés sur la pile plutôt que sur le tas en tant qu'optimisation de performance. (Source)
Les JVM peuvent utiliser une technique appelée analyse d'évasion, par laquelle elles peuvent déterminer que certains objets restent confinés à un seul thread pendant toute leur durée de vie et que cette durée de vie est limitée par la durée de vie d'un cadre donné. De tels objets peuvent être en toute sécurité alloués sur la pile au lieu du tas.
Et comme une image vaut mille mots, voici une de James Bloom
Maintenant répondant à certaines de vos questions :
Comment la JVM sait-elle combien de threads seront créés ?
Elle ne le sait pas. Cela peut être facilement prouvé par contradiction en créant un nombre variable de threads. Elle fait certaines hypothèses sur le nombre maximum de threads et la taille de la pile de chaque thread. C'est pourquoi vous pouvez manquer de mémoire (sans signifier la mémoire du tas !) si vous allouez trop de threads.
Java crée-t-il une pile pour chaque thread lorsqu'il est créé ?
Comme mentionné précédemment, chaque thread de la machine virtuelle Java a une pile privée de la machine virtuelle Java, créée en même temps que le thread. (Source).
Si oui, où exactement se trouve la pile dans la mémoire ? Ce n'est certainement pas dans le tas "géré".
Comme indiqué ci-dessus, la spécification Java permet à la mémoire de la pile d'être stockée sur le tas, techniquement parlant. Mais au moins la JVM JRockit utilise une partie de mémoire différente.
La JVM crée-t-elle la pile à partir de la mémoire native ou pré-alloue-t-elle une section de la zone de mémoire gérée pour la pile ?
La pile est gérée par la JVM car la spécification Java prescrit comment elle doit se comporter : Une pile de la machine virtuelle Java stocke des cadres (§2.6). Une pile de la machine virtuelle Java est analogue à la pile d'un langage conventionnel. Une exception sont les piles de méthodes natives utilisées pour les méthodes native
. Plus à ce sujet à nouveau dans la spécification.