Wenn ich ein Objekt erstelle, wird frischer Speicher sowohl Instanzfeldern als auch Methoden oder nur Instanzfeldern zugewiesen

14

Ich habe eine folgende Klasse

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);

}
}

Jetzt erstelle ich zwei Objekte vom Typ Student wie folgt

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

Nun werden zwei verschiedene Speichersätze für Instanzfelder zugewiesen. Jetzt ist meine Frage, ob Speicher für Methoden ( setResultund displayResult) zweimal oder einmal reserviert wird ?

Bitte sehen Sie sich die folgende Abbildung an und können Sie mir dabei helfen, zu sagen, welche Abbildung die richtigen Informationen enthält.

Bildbeschreibung hier eingeben

Harish_N
quelle
1
Das Teilen Ihrer Forschung hilft allen . Sagen Sie uns, was Sie versucht haben und warum es nicht Ihren Bedürfnissen entsprach. Dies zeigt, dass Sie sich die Zeit genommen haben, um sich selbst zu helfen, es erspart uns, offensichtliche Antworten zu wiederholen, und vor allem hilft es Ihnen, eine spezifischere und relevantere Antwort zu erhalten. Siehe auch Wie man fragt
Mücke
3
Ich lerne Java ... und in allen Materialien wird nur gesagt, dass bei jedem Erstellen eines Objekts allen Instanzfeldern ein neuer Speicher zugewiesen wird. Aber in keinem der Materialien wird angegeben, ob neuer Speicher für Methoden oder zugewiesen wird nicht
Harish_N

Antworten:

13

Der Code für Methoden ist Teil von Class(genauer gesagt Class<Student>) und wird beim ersten Laden der Klasse in den Speicher geladen.

Das heißt, wenn Sie eine Methode ausführen, wird zusätzlicher Speicher verwendet, um Parameter, lokale Variablen, temporäre Ausdrucksergebnisse, Rückgabewerte usw. zu speichern. Dieser Speicher wird jedoch im Stack zugewiesen (der beim Erstellen einer neuen Instanz verwendete Speicher wird im Heap zugewiesen) .

Gemäß Ihrer Frage sollte jetzt klar sein, dass Abbildung B korrekt ist (obwohl es nicht widerspiegelt, was passiert, wenn Sie die Methode tatsächlich aufrufen).

SJuan76
quelle
In Ordnung. Ich bin jetzt zu 90% klar. Aber ein kleiner Zweifel. Angenommen, wenn ich 10 Objekte vom Typ Student erstelle, wird den in der Klasse Student vorhandenen Methoden nur 1 Satz frischen Speichers zugewiesen, während 10 Sätze frischen Speichers vorhanden sind zugewiesen, um Instanzvariablen für 10 Objekte zu speichern .. Bin ich richtig?
Harish_N
Richtig. Denken Sie, dass nicht nur die Eigenschaften Speicher beanspruchen, sondern auch ein geringer Overhead in Bezug auf die Instanz selbst entsteht (eine Instanz einer Klasse ohne Eigenschaften belegt mehr als 0 Byte Speicher).
SJuan76
Noch eine Sache ... Ich stellte eine Frage, wobei ich Java im Hinterkopf hatte ...
Geschieht
Die Java-Sprachspezifikation sagt nichts darüber aus, wie viel Speicher wann und zu welchem ​​Zweck zugewiesen wird. Das bleibt dem Implementierer überlassen, und jeder Implementierer kann anders wählen.
Jörg W Mittag
6

Instanzfelder (einschließlich Eigenschafts-Hintergrundfelder) erhalten N-Kopien für N-Objekte.

Statische Felder erhalten eine einzelne Kopie pro Klasse.

Methoden sind Bytecode-Blöcke (oder nach JIT Blöcke nativer Anweisungen), die Teil des Programms "image" oder des ausführbaren Codesegments sind. Methoden sind bereits Teil des Programmimages, da es sich auf der Festplatte befindet. Sobald das Image vom Betriebssystem (oder CLR) geladen wurde, gibt es eine einzige gemeinsam genutzte Kopie des Methodencodes.

Sie sind im Allgemeinen kein Teil der Heap- oder Laufzeitzuweisung, außer in Fällen, in denen Sie den hostfähigen Compiler verwenden können, um neue Methoden im laufenden Betrieb zu kompilieren. Methoden werden nicht wie Objekte "zugewiesen" und sie werden nicht im Verhältnis zur Objekterstellung "zugewiesen". Sie existieren lediglich als Teil des Programms, bevor ein einzelnes Objekt jemals instanziiert wird. Selbst Lambdas / Delegierte werden nicht im laufenden Betrieb zugeteilt. Der Compiler erstellt bei Bedarf Klassen, um diese anderen scheinbar dynamischen Codeobjekte zu implementieren, und sie sind auch als Teil des Bytecode-Image auf der Festplatte vorhanden.

UPDATES per Kommentare:

Der JVM-Standard hat Folgendes zu sagen:

2.5.4. Methodenbereich

Die Java Virtual Machine verfügt über einen Methodenbereich, der von allen Java Virtual Machine-Threads gemeinsam genutzt wird. Der Methodenbereich ist analog zum Speicherbereich für kompilierten Code einer herkömmlichen Sprache oder analog zum "Text" -Segment in einem Betriebssystemprozess. Es speichert Strukturen pro Klasse, wie den Laufzeitkonstantenpool, Feld- und Methodendaten sowie den Code für Methoden und Konstruktoren, einschließlich der speziellen Methoden (§2.9), die bei der Klassen- und Instanzinitialisierung und Schnittstelleninitialisierung verwendet werden.

Der Methodenbereich wird beim Start der virtuellen Maschine erstellt. Obwohl der Methodenbereich logischerweise Teil des Heaps ist, kann es bei einfachen Implementierungen vorkommen, dass weder Garbage Collect noch eine Komprimierung vorgenommen werden. Diese Version der Java Virtual Machine-Spezifikation schreibt weder den Speicherort des Methodenbereichs noch die zum Verwalten von kompiliertem Code verwendeten Richtlinien vor. Der Methodenbereich kann eine feste Größe haben oder kann erweitert werden, wie es die Berechnung erfordert, und kann verkleinert werden, wenn ein größerer Methodenbereich unnötig wird. Der Speicher für den Methodenbereich muss nicht zusammenhängend sein.

Es ist also klar, dass (1) ja die Spezifikation nicht vorschreibt, wie dies getan wird, aber (2) es ist analog zum Speicherbereich für kompilierten Code einer herkömmlichen Sprache, dh. das Textsegment. Das ist der Punkt, den ich mache.

Codenheim
quelle
Was Sie sagen, macht Sinn, aber ist das tatsächlich durch die JLS garantiert? Normalerweise lässt der JLS den Implementierern bei Fragen wie diesen viel Spielraum.
Jörg W Mittag
Da bin ich mir nicht sicher, @ JörgWMittag. Du könntest Recht haben. Der Punkt, den ich ansprechen wollte, ist, dass "new T ()" keine neue Instanz einer Methode zuweist. Was die Besonderheiten der JVM angeht, speichern Classloader tatsächlich Bytecode im Heap, und ich denke, es gibt mögliche Szenarien, in denen Klassen selbst instanziiert und sogar Müll gesammelt werden. Aber es ist ein Implementierungsdetail der Laufzeit, und konzeptionell ist der Heap, von dem ich spreche, der "Benutzer" -Heap. Die Klassen und Methoden werden im normalen Benutzerkontext nicht als Daten betrachtet. Da wir aber auch einen Classloader vom Userland aus steuern können, weiß ich es wohl nicht.
Codenheim
Die JLS spricht überhaupt nicht von einem Haufen, oder? Es ist vollkommen legal, Java mit einem dynamischen Stapel und keinem Heap zu implementieren, anstatt mit einem endlichen Stapel fester Größe und einem dynamischen Heap. Das JLS sagt auch nichts über die JVM aus, es ist durchaus gültig, Java ohne eine JVM zu implementieren.
Jörg W Mittag
Sie verweisen auf JLS, aber ich spreche von JVM. Der JVM-Standard beschreibt sicherlich Heap. Sie müssen einen variablen Bereich / eine variable Lebensdauer angeben, der / die dem lokalen Bereich des Stapels entgeht. Was theoretisch möglich ist, denke ich lieber in "bekannten Implementierungen". Ich bin mir ziemlich sicher, dass die Implementierung einer vollständigen JVM ohne ein Heap-Primitiv eine schwierige oder sogar unmögliche Aufgabe ist, da die JVM keine reine Stapelmaschine ist. Mein Verständnis der Forth-Maschinen und anderer reiner Stapelarchitekturen ist, dass es möglich ist, wenn ein Grundelement für den wahlfreien Variablenzugriff vorhanden ist, aber ich habe es einfach nicht gesehen.
Codenheim
@ JörgWMittag - Ich habe der Antwort etwas hinzugefügt, das für unsere Diskussion von Interesse sein könnte. Der Punkt ist, dass ich eine Analogie zum traditionellen Code oder Textsegment in herkömmlichen Laufzeitsystemen gezeichnet habe.
Codenheim
-4

Objekt im Heap-Speicher zugewiesen. Wenn Objekt zugewiesen wird, wird der Steckplatz für alle Instanzvariablen erstellt und zerstört, wenn das Objekt zerstört wird. So wird Instanzvariable auch im Heap-Speicher zugewiesen Methode aufgerufen werden.

Abhishek Tripathi
quelle
1
Dies scheint nur die Informationen zu wiederholen, die in früheren Antworten bereitgestellt wurden.