Je connais le concept d'un pool de constantes et le pool de constantes String utilisé par les JVM pour gérer les littéraux String. Mais je ne sais pas quel type de mémoire est utilisé par la JVM pour stocker les littéraux constants String. La pile ou le tas? Puisqu'il s'agit d'un littéral qui n'est associé à aucune instance, je suppose qu'il sera stocké dans la pile. Mais s'il n'est référencé par aucune instance, le littéral doit être collecté par GC run (corrigez-moi si je me trompe), alors comment cela est-il géré s'il est stocké dans la pile?
104
Réponses:
La réponse n'est techniquement ni l'un ni l'autre. Selon la spécification de la machine virtuelle Java, la zone de stockage des littéraux de chaîne se trouve dans le pool de constantes d'exécution . La zone de mémoire du pool de constantes d'exécution est allouée par classe ou par interface, elle n'est donc pas du tout liée à des instances d'objet. Le pool de constantes d'exécution est un sous-ensemble de la zone de méthode qui qui "stocke les structures par classe telles que le pool de constantes d'exécution, les données de champ et de méthode, et le code des méthodes et des constructeurs, y compris les méthodes spéciales utilisées dans l'initialisation et l'interface de classe et d'instance. initialisation de type ". La spécification VM indique que bien que la zone de méthode fait logiquement partie du tas, il ne dicte pas que la mémoire allouée dans la zone de méthode soit soumise au garbage collection ou à d'autres comportements qui seraient associés aux structures de données normales allouées au tas .
la source
Comme expliqué par cette réponse , l'emplacement exact du pool de chaînes n'est pas spécifié et peut varier d'une implémentation JVM à une autre.
Il est intéressant de noter que jusqu'à Java 7, le pool se trouvait dans l'espace permgen du tas sur hotspot JVM mais il a été déplacé vers la partie principale du tas depuis Java 7 :
Et dans Java 8 Hotspot, la génération permanente a été complètement supprimée.
la source
Les littéraux de chaîne ne sont pas stockés sur la pile. Jamais. En fait, aucun objet n'est stocké sur la pile.
Les littéraux de chaîne (ou plus précisément les objets String qui les représentent)
sonthistoriquement stockés dans un tas appelé le tas "permgen". (Permgen est l'abréviation de génération permanente.)Dans des circonstances normales, les littéraux de chaîne et la plupart des autres éléments du tas permgen sont accessibles "en permanence" et ne sont pas récupérés. (Par exemple, les littéraux de chaîne sont toujours accessibles à partir des objets de code qui les utilisent.) Cependant, vous pouvez configurer une machine virtuelle Java pour tenter de trouver et de collecter des classes chargées dynamiquement qui ne sont plus nécessaires, ce qui peut entraîner la récupération des déchets de littéraux de chaîne. .
CLARIFICATION # 1 - Je ne dis pas que Permgen n'obtient pas GC. C'est le cas, généralement lorsque la JVM décide d'exécuter un GC complet. Mon point est que les littéraux de chaîne seront accessibles tant que le code qui les utilise est accessible, et le code sera accessible tant que le chargeur de classe du code est accessible, et pour les chargeurs de classe par défaut, cela signifie "pour toujours".
CLARIFICATION # 2 - En fait, Java 7 et les versions ultérieures utilisent le tas normal pour contenir le pool de chaînes. Ainsi, les objets String qui représentent les littéraux String et les chaînes internes sont en fait dans le tas normal. (Voir la réponse de @ assylias pour plus de détails.)
Il n'y a pas de «ligne fine». C'est vraiment très simple:
String
les objets qui représentent / correspondent à des chaînes littérales sont conservés dans le pool de chaînes.String
les objets créés par unString::intern
appel sont conservés dans le pool de chaînes.String
objets ne sont PAS contenus dans le pool de chaînes.Ensuite, il y a la question distincte de savoir où le pool de chaînes est "stocké". Avant Java 7, c'était le tas permgen. À partir de Java 7, c'est le tas principal.
la source
Regroupement de chaînes
String.intern () dans Java 6
String.intern () dans Java 7
Les valeurs du pool de chaînes sont récupérées
la source.
la source
Comme d'autres réponses l'expliquent, la mémoire en Java est divisée en deux parties
1. Pile: Une pile est créée par thread et elle stocke des cadres de pile qui stockent à nouveau des variables locales et si une variable est un type de référence alors cette variable fait référence à un emplacement de mémoire dans le tas pour l'objet réel.
2. Heap: tous les types d'objets seront créés uniquement dans le tas.
La mémoire du tas est à nouveau divisée en 3 parties
1. Young Generation: Stocke les objets qui ont une durée de vie courte, Young Generation elle-même peut être divisée en deux catégories Eden Space et Survivor Space .
2. Ancienne génération: stockez les objets qui ont survécu à de nombreux cycles de garbage collection et qui sont toujours référencés.
3. Génération permanente: stocke les métadonnées sur le programme, par exemple le pool de constantes d'exécution.
Le pool de constantes de chaîne appartient à la zone de génération permanente de la mémoire du tas.
Nous pouvons voir le pool de constantes d'exécution pour notre code dans le bytecode en utilisant
javap -verbose class_name
ce qui nous montrera les références de méthode (#Methodref), les objets de classe (#Class), les littéraux de chaîne (#String)Vous pouvez en savoir plus à ce sujet dans mon article Comment la JVM gère-t-elle la surcharge et le remplacement de méthode en interne .
la source
Aux bonnes réponses déjà incluses ici, je veux ajouter quelque chose qui manque à mon point de vue - une illustration.
Comme vous l'avez déjà fait, JVM divise la mémoire allouée à un programme Java en deux parties. un est pile et un autre est tas . La pile est utilisée à des fins d'exécution et le tas est utilisé à des fins de stockage. Dans cette mémoire de tas, JVM alloue de la mémoire spécialement conçue pour les littéraux de chaîne. Cette partie de la mémoire du tas est appelée pool de constantes de chaîne .
Ainsi, par exemple, si vous initiez les objets suivants:
Les littéraux de chaîne
s1
ets2
iront dans le pool de constantes de chaîne, les objets obj1, obj2, obj3 dans le tas. Tous seront référencés à partir de la pile.Notez également que "abc" apparaîtra dans le tas et dans le pool de constantes de chaîne. Pourquoi est-ce
String s1 = "abc"
etString obj1 = new String("abc")
sera-t-il créé de cette façon? C'est parce queString obj1 = new String("abc")
crée explicitement une instance nouvelle et référentiellement distincte d'un objet String etString s1 = "abc"
peut réutiliser une instance du pool de constantes de chaîne si elle est disponible. Pour une explication plus élaborée: https://stackoverflow.com/a/3298542/2811258la source