8
votes

Pourquoi les types de référence sont-ils stockés dans le tas

Je sais que dans Java, (peut-être aussi dans .net aussi), les primitives sont stockées sur des piles, où les types de référence sont stockés sur des tas.

Ma question était que je ne comprends pas la procuration de ce comportement. Pourquoi ne pouvons-nous pas faire référence à un emplacement de mémoire à l'intérieur de nos piles? . Je ne pouvais pas trouver une explication appropriée alors que je googled (peut-être que je le suce), mais si vous pouvez fournir des idées, je serais reconnaissant

merci.


2 commentaires

Ceci est répondu ici: programmeurs.stackexchange.com/questions/142024/...


Merci pour vos réponses, j'ai une vision claire à ce sujet maintenant.


4 Réponses :


9
votes

Je sais que dans Java, (peut-être en .NET aussi), les primitives sont stockées sur des piles, où les types de référence sont stockés sur des tas. P>

Non. Il fait pas strong> dépend de sa primitive ou d'une référence. Cela dépend de la portée forte> si la pile ou le tas est utilisée. Les variables locales sont allouées sur la pile, des variables de membre sont allouées sur le tas lorsque l'objet est instancié. P>

Voir aussi Les primitives Java vont-elles sur la pile ou le tas? P>

Ma question était que je ne comprends pas la procuration de ce comportement. P> blockQuote>

Les données stockées sur la pile ne vivent que tant que votre méthode est exécutée. Une fois la méthode terminée, toutes les données allouées sur la pile sont supprimées. Les données stockées sur le tas vit aussi longtemps que cela n'est pas jeté (ce qui, en cas de java, est fait en arrière-plan par le collecteur des ordures). Dans d'autres langues telles que C / C ++, vous devez explicitement supprimer des données / libres qui ont été allouées sur le tas. P>

Considérez l'extrait de code suivant: P>

String someMethod() {
  int i = 0;
  String result = "Hello";

  i = i + 5;
  return result;
}


2 commentaires

J'allais bien avec votre explication, jusqu'à ce que vous ayais dit. La référence est allouée sur la pile, mais l'objet (un objet de chaîne dans ce cas) est attribué sur le tas que je comprends que comme la méthode commence, integer "I" aurait 2 octets (selon la plate-forme) et disparaîtrait une fois la méthode terminée. Cependant, vous dites que le "résultat" serait également attribué la mémoire sur la pile, ainsi que dans le tas? Ou impliquez-vous que seul un pointeur sur un emplacement de mémoire dans le tas serait existé pendant l'exécution de la méthode.


@MuhammadahMédabutalib exactement - il suffit de dire qu'une référence est un pointeur sur l'objet et ce pointeur est attribué sur la pile, tandis que l'objet lui-même est attribué sur le tas. L'objet lui-même peut contenir d'autres primitives et autres références en tant que membres, auquel cas ils seraient alloués sur le tas lorsque l'objet est instancié.



0
votes

Pourquoi ne pouvons-nous pas faire référence à un emplacement de mémoire à l'intérieur de nos piles?

Vous pouvez, mais penser à cette décision comme Décision d'architecture de la mémoire.

Par concept, idéalement, toutes les données ne peuvent pas être récupérées à partir de pile si ce n'est pas sur le dessus. Mais dans le monde réel, vous avez besoin d'un emplacement à accéder à partir de n'importe où dans le programme. Donc, ça ne peut pas être pile. et ils l'ont nommé tas .

Ce lien peut jeter plus de lumière dessus.


0 commentaires

1
votes

où les types de référence sont stockés sur des tas.

Je ne sais pas ce que vous entendez exactement par cette partie, mais rappelez-vous que seuls les objets sont stockés sur tas , tandis que les références pointant sur ces objets sont toujours sur la pile. C'était probablement le doute que vous ayez eu.

Maintenant, vous devez également noter que seules les variables locales sont stockées sur Stack , tandis que instance / membre> variables sont stockés sur tas .

pour par exemple: - xxx

dans le cas ci-dessus, str référence sera attribué la mémoire sur pile , si bien sûr, il est défini dans une portée locale. Et cela indiquera un nouvel objet String créé sur tas .


6 commentaires

Merci pour la réponse, c'est simple et pourtant descriptif. Cependant, veuillez aussi noter que je voulais savoir "pourquoi". Pouvez-vous perdre une lumière sur la raison pour laquelle le tas, pourquoi ne pouvons-nous pas simplement utiliser la pile. Est-ce parce que la pile est la principale "zone de travail" et cela change son état, car le code s'exécute donc ne peut être considéré comme un espace réservé aux globaux? .


Et oui, mes types de référence que vous avez correctement déduit ce que je voulais dire, vous avez effacé les confusions que j'ai eues à coup sûr. Mais juste ce bit reste


Chaque appel de méthode est stocké sur la pile. Parallèlement à ceux qui sont stockés tous les paramètres que nous transmettons, et les variables locales créées. Maintenant, la pile stocke ces paramètres et variables locales est distribuée dès que l'exécution sort de la méthode. Et leur application se termine. Et donc il y a une meilleure gestion de la mémoire. Maintenant, si nous parlons d'objets, rappelez-vous une chose qui, les objets créés dans une seule portée peuvent être utilisés dans une autre portée, s'il détient une référence à cet objet. Donc, ils ne doivent pas être stockés sur la pile.


Comprenons de cette façon. Lorsque vous appelez une méthode d'une autre méthode. Les références que vous passez sont copiées dans la pile créée pour cette méthode. Et cela pointe vers le même objet, car la référence initiale indiquait. Donc, maintenant, vous avez deux références sur deux piles pointant vers un même objet sur le tas. Demandez si vous avez besoin d'une explication plus claire.


Ainsi, un avantage de stocker des objets sur le tas, est que vous pouvez y accéder de l'extérieur de la portée où il a été créé.


Merci pour vos réponses, Rohit Jain. Ils m'ont aidé dans une perspicacité claire. Aussi à ajouter que j'ai un très bon ami par votre même nom à Banglore. :)



6
votes

Vous ne pouvez généralement pas stocker les types de référence sur la pile car le cadre de pile est détruit lors de la déclaration de méthode. Si vous avez enregistré une référence à un objet afin qu'il puisse être déréférencé après la fin de la méthode, vous seriez la déséroférience d'un emplacement de pile inexistant.

Le hotspot jvm peut exécuter Analyse d'évacuation et, s'il détermine qu'un objet ne peut éventuellement échapper à la portée de la méthode, elle l'allouera en fait sur la pile.


5 commentaires

Ainsi, vous impliquez que la décision de stocker un morceau de données soit dans la pile ou le tas, n'a rien à voir avec le fait qu'il s'agit d'un type primitif ou d'un type de référence? Cela concerne plutôt le fait que si c'est global ou local? . Si cela est vrai, toute ma vie était un mensonge, je pensais que peu importe si je faisais ABC Obj = New ABC (), l'espace pour ABC entrerait toujours dans le tas.


Si c'est primitif, alors il est définitivement sur la pile , donc votre "rien à faire" est faux. Mais oui, la JVM a le verdict final sur l'endroit où l'objet réside, car cela détaille strictement un détail de mise en œuvre. C'est pourquoi je ne vois pas une raison pour laquelle quelqu'un passerait du temps à m'inquiéter à ce sujet.


Vous devez distinguer l'espace pour abc et l'espace de référence (type de pointeur) sur abc . Dans ABC Obj = New ABC () , la mémoire est allouée sur le tas pour stocker l'objet abc et (supposé la ligne de code comme écrit fait partie d'un organisme de méthode) L'espace pour le obj référence est attribué sur la pile.


Une dernière question marko, vous êtes correct, je ne devrais pas m'inquiéter de ces détails, mais la curiosité tue. Si censé ABC est dans un organe de méthode, de telle sorte qu'il est de nature locale et n'est référencé nulle part ailleurs dans l'ensemble du programme dans une telle situation, selon votre commentaire précédent, l'espace de référence et l'espace pour ABC, tous deux être en pile?


Oui, c'est correct, mais notez qu'il y a plus de conditions préalables, comme ne jamais transmettre la référence à d'autres méthodes, car l'analyseur de code statique dans le compilateur JIT ne peut pas être sûr de ce que cette méthode pourrait faire, en particulier face à la répartition dynamique . Google pour "Analyse d'évasion Hotspot" pour creuser dans les détails fins.