Lorsque je crée un objet, de la mémoire fraîche est-elle allouée aux champs et méthodes d'instance ou uniquement aux champs d'instance

14

J'ai un cours suivant

class Student{

int rollNumber;
int marks;

public void setResult(int rollNumber, int marks){

    this.rollNumber=rollNumber;
    this.marks=marks;   
}

public void displayResult(){

    System.out.println("Roll Number= "+this.rollNumber+"   Marks= "+this.marks);

}
}

Maintenant, je crée deux objets de type Student comme suit

Student s1=new Student();
Student s2=new Student();

Maintenant, deux ensembles différents de mémoire sont alloués pour les champs d'instance. Maintenant, ma question est de savoir si la mémoire est allouée aux méthodes ( setResultet displayResult) deux ou une fois?

Veuillez consulter la figure suivante et pouvez-vous m'aider à dire quelle figure donne les informations correctes.

entrez la description de l'image ici

Harish_N
la source
1
Partager vos recherches aide tout le monde . Dites-nous ce que vous avez essayé et pourquoi cela n'a pas répondu à vos besoins. Cela démontre que vous avez pris le temps d'essayer de vous aider, cela nous évite de réitérer des réponses évidentes et, surtout, cela vous aide à obtenir une réponse plus spécifique et pertinente. Voir aussi How to Ask
gnat
3
J'apprends java ... et dans tous les matériaux, ils disent simplement que chaque fois que nous créons un objet, une nouvelle mémoire est allouée à tous les champs d'instance. pas
Harish_N

Réponses:

13

Le code des méthodes fait partie de Class(de manière plus concise Class<Student>) et il est chargé en mémoire lors du premier chargement de la classe.

Cela dit, lorsque vous exécutez une méthode, une mémoire supplémentaire est utilisée pour allouer de la mémoire aux paramètres, aux variables locales, aux résultats des expressions temporaires, aux valeurs de retour, etc. Mais cette mémoire est allouée dans la pile (la mémoire utilisée lors de la création d'une nouvelle instance est allouée dans le tas .

Selon votre question, il devrait être clair maintenant que la figure B est correcte (bien qu'elle ne reflète pas ce qui se passe lorsque vous appelez réellement la méthode).

SJuan76
la source
D'accord. Je suis clair à 90% maintenant .... Mais un petit doute .. Supposons que si je crée 10 objets de type Student alors seulement 1 jeu de mémoire fraîche est alloué aux méthodes présentes dans la classe Student alors que 10 jeux de mémoire fraîche sont alloué pour stocker des variables d'instance pour 10 objets ... Ai-je raison?
Harish_N
Droite. Pensez que ce ne sont pas seulement les propriétés qui prennent de la mémoire, il y a une petite surcharge liée à l'instance elle-même (une instance d'une classe sans propriétés utilisera plus de 0 octet de mémoire).
SJuan76
Encore une chose ... J'ai posé une question en gardant java à l'esprit .... Est-ce que la même chose se produit en java .....
Harish_N
La spécification du langage Java ne dit rien sur la quantité de mémoire allouée quand et dans quel but. Cela est laissé à l'implémenteur, et chaque implémenteur peut choisir différemment.
Jörg W Mittag
6

Les champs d'instance (y compris les champs de support de propriété) obtiennent N-copies pour N-objets.

Les champs statiques obtiennent une seule copie par classe.

Les méthodes sont des blocs de bytecode (ou après JIT, des blocs d'instructions natives) qui font partie de "l'image" du programme ou du segment de code exécutable. Les méthodes font déjà partie de l'image du programme car elle se trouve sur le disque. Une fois que l'image est chargée par le système d'exploitation (ou CLR), il existe une seule copie partagée du code de méthode.

Ils ne font généralement pas partie du "tas" ou de l'allocation d'exécution, sauf dans les cas où vous pouvez utiliser le compilateur hébergeable pour compiler de nouvelles méthodes à la volée. Les méthodes ne sont pas "allouées" comme les objets et elles ne sont pas "allouées" par rapport à la création d'objet. Ils existent simplement dans le cadre du programme avant qu'un seul objet ne soit instancié. Même les lambdas / délégués ne sont pas attribués à la volée. Le compilateur crée des classes à la demande pour implémenter ces autres objets de code apparemment dynamiques, et ils existent également dans le cadre de l'image de bytecode sur le disque.

MISES À JOUR par commentaires:

La norme JVM a ceci à dire:

2.5.4. Zone de méthode

La machine virtuelle Java a une zone de méthode qui est partagée entre tous les threads de la machine virtuelle Java. La zone de procédé est analogue à la zone de stockage pour le code compilé d'un langage conventionnel ou analogue au segment "texte" dans un processus de système d'exploitation. Il 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 constructeurs, y compris les méthodes spéciales (§2.9) utilisées dans l'initialisation de classe et d'instance et l'initialisation d'interface.

La zone de méthode est créée au démarrage de la machine virtuelle. Bien que la zone de méthode fasse logiquement partie du tas, les implémentations simples peuvent choisir de ne pas effectuer de récupération de place ou de la compacter. Cette version de la spécification Java Virtual Machine ne requiert pas l'emplacement de la zone de méthode ni les politiques utilisées pour gérer le code compilé. La zone de méthode peut être d'une taille fixe ou peut être étendue selon les besoins du calcul et peut être contractée si une zone de méthode plus grande devient inutile. La mémoire de la zone de méthode n'a pas besoin d'être contiguë.

Il est donc clair que (1) oui, la spécification ne dicte pas comment cela est fait, mais (2) elle est analogue à la zone de stockage pour le code compilé d'un langage conventionnel, c'est-à-dire. le segment de texte. C'est le point que je fais valoir.

codenheim
la source
Ce que vous dites est logique, mais est-ce réellement garanti par le JLS? Normalement, le JLS donne aux implémenteurs une grande latitude dans des questions comme celle-ci.
Jörg W Mittag
Pas sûr sur ce point, @ JörgWMittag. Vous pouvez avoir raison. Le point que j'ai essayé de faire est que "new T ()" n'alloue pas une nouvelle instance d'une méthode. En ce qui concerne les spécificités de la JVM, les chargeurs de classe stockent en effet le bytecode dans le tas, et je suppose qu'il existe des scénarios possibles où les classes elles-mêmes sont instanciées et même récupérées. Mais c'est le détail d'implémentation du runtime, et conceptuellement, le tas dont je parle est le tas "utilisateur". La classe et les méthodes ne sont pas considérées comme des données dans le contexte utilisateur normal. Mais comme nous pouvons également contrôler un chargeur de classe à partir de l'espace utilisateur, je suppose que je ne sais pas.
codenheim
Le JLS ne parle même pas d'un tas du tout, n'est-ce pas? Il est parfaitement légal d'implémenter Java avec une pile dynamique et sans tas au lieu d'une pile de taille fixe finie et d'un tas dynamique. Le JLS ne dit rien sur la JVM, il est parfaitement valable d'implémenter Java sans JVM.
Jörg W Mittag
Vous faites référence à JLS, mais je parle de JVM. La norme JVM traite certainement du tas. Vous devez fournir une étendue / durée de vie variable qui échappe à l'étendue locale de la pile. Quant à ce qui est théoriquement possible, je préfère penser en termes de "mises en œuvre connues". Je suis à peu près sûr que la mise en œuvre d'une JVM complète sans primitive de tas est un travail difficile, voire impossible, car la JVM n'est pas une machine à pile pure. Ma compréhension des machines Forth, et d'autres architectures de pile pure, est qu'il peut être possible s'il existe une primitive pour l'accès aléatoire aux variables, mais je ne l'ai tout simplement pas vue.
codenheim
@ JörgWMittag - J'ai ajouté à la réponse quelque chose qui peut être intéressant pour notre discussion. Le fait est que je faisais une analogie avec le segment de code ou de texte traditionnel dans les systèmes d'exécution conventionnels.
codenheim
-4

objet alloué dans la mémoire de tas.Lorsque l'objet est alloué, l'emplacement pour toute la variable d'instance est créé et détruit lorsque l'objet est détruit.Ainsi, la variable d'instance est également allouée dans la mémoire de tas.Et la variable locale est créée en pile au moment où sont appelées.

Abhishek Tripathi
la source
1
Cela semble simplement répéter les informations fournies dans les réponses précédentes.