Java-Stack- und Heap-Speicherverwaltung

10

Ich möchte wissen, wie der Speicher im folgenden Programm zugewiesen wird:

%Vor%

Nun, nach meinem Verständnis, beschreibt das folgende Diagramm, wie die Speicherzuweisung erfolgt:


Im obigen Diagramm sind Speicher , obj und s , die sich im Stapelspeicher befinden, tatsächlich die Referenzen auf ihre " tatsächliche" Objekte ", die im Heap-Speicher abgelegt sind.
Hier sind die Fragen, die mir in den Sinn kommen:

  1. Wo sind die Methoden von s gespeichert?
  2. Hätte ich ein anderes Objekt von MemoryClass in myMethod erstellt, würde JVM dann wieder Speicher für die gleichen Methoden im Stapelspeicher reservieren?
  3. Würde JVM den Speicher freigeben, der myMethod zugewiesen ist, sobald die Ausführung abgeschlossen ist, wenn ja, wie würde er die in Frage 2 erwähnte Situation handhaben ( nur anwendbar, wenn JVM Speicher mehrfach derselben Methode zuweist) ).
  4. Was wäre der Fall gewesen, wenn ich nur s deklariert und es nicht initialisiert hätte, würde JVM trotzdem allen Methoden von java.lang.String class Speicher zuweisen, wenn ja, warum?
Adit A. Pillai 13.12.2016, 11:34
quelle

3 Antworten

12
  

Wo sind die Methoden von s gespeichert?

Sie werden im String-Klassenobjekt gespeichert; Es ist ein Objekt, das von einem ClassLoader-Objekt geladen wird, wenn im Programm zum ersten Mal auf String verwiesen wird. Alle Implementierungen der JVM, die existierten, als ich darüber las, haben den Speicher für ein Klassenobjekt nach dem Laden nie freigegeben. Es ist auf dem Haufen.

  

Hätte ich innerhalb von myMethod ein anderes Objekt von MemoryClass erstellt, würde JVM dann wieder Speicher für die gleichen Methoden innerhalb des Stack-Speichers reservieren?

Nein, Methoden und Daten für Objekte werden separat aufbewahrt, insbesondere weil die JVM niemals mehr als eine Kopie der Methoden benötigt.

  

Würde JVM den der myMethod zugewiesenen Speicher freigeben, sobald die Ausführung abgeschlossen ist, und wenn ja, wie würde er die in Frage 2 erwähnte Situation handhaben (gilt nur, wenn JVM der gleichen Methode mehrmals Speicher zuweist).

Nein. Java "im Allgemeinen nicht" sofort Speicher von Dingen frei, die auf dem Haufen gespeichert werden. Es würde die Dinge zu langsam laufen lassen. Es gibt nur Speicher frei, wenn der Garbage Collector ausgeführt wird, und dies nur dann, wenn sein Algorithmus zum Ausführen des Garbage Collectors entscheidet, dass es Zeit ist.

  

Was wäre der Fall gewesen, wenn ich nur s deklariert hätte und es nicht initialisiert hätte, würde JVM noch allen Methoden der java.lang.String-Klasse Speicher zuweisen, wenn ja, warum?

Das hängt von der JVM-Implementierung ab, denke ich, und vielleicht vom Compiler. Wenn Sie eine Variable deklarieren und sie nie verwenden, ist es durchaus möglich (und üblich), dass der Compiler bemerkt, dass er nicht verwendet wird und dass er nicht in die Klassendatei eingefügt wird. Wenn es nicht in der Klassendatei ist, wird es nie referenziert, und daher werden es und seine Methoden nicht geladen usw. Wenn der Compiler es trotzdem einfügt, aber nie referenziert wird, hätte der ClassLoader keinen Grund dazu lade es, aber ich bin ein wenig vage darüber, ob es geladen wird oder nicht. Könnte von der JVM-Implementierung abhängen; lädt es Dinge, weil es Variablen der Klasse gibt oder nur wenn sie referenziert sind? Wie viele ClassLoader-Algorithmen können auf dem Kopf einer 4-stelligen PIN tanzen?

Ich ermutige Sie, über JVM und ClassLoaders und so weiter zu lesen; Sie werden so viel mehr gewinnen, wenn Sie eine Erklärung dafür lesen, wie es funktioniert, anstatt es mit Beispielen zu durchforsten, die Sie sich ausdenken können.

    
arcy 13.12.2016, 11:54
quelle
5

Erste Dinge zuerst : Ich gehe davon aus, dass Ihre Fragen nach dem Lesen von diesen Artikel (, da drüben sehe ich ein sehr ähnliches Diagramm wie Ihres ), also werde ich keine der Punkte zitieren oder hervorheben Da drüben erwähnt und versuchen werden, auf Ihre Fragen mit Punkten zu antworten, die in diesem Beitrag nicht so offensichtlich waren.

Wenn ich all Ihre Fragen lese, habe ich den Eindruck, dass Sie sich darüber im Klaren sind, wie Speicher in Stack und Heap zugeordnet ist, aber Zweifel an Metadaten der Klassen haben, dh wo im Speicher die Methoden der Klassen gespeichert werden und wie sie aussehen würden recycelt werden. Lassen Sie mich zunächst versuchen, JVM-Speicherbereiche zu erklären:

JVM Speicherbereiche

Lassen Sie mich zu Beginn diese 2 Diagramme mit JVM-Speicherbereichen einfügen:

Quelle des Diagramms

Quelle des Diagramms

Nun, wie aus den obigen Diagrammen hervorgeht, ist die Baumstruktur des JVM-Speichers und ich werde versuchen, dasselbe zu beleuchten ( @Adit: Bitte beachten Sie, dass der Bereich PermGen Space oder permanenter Generierungsraum ist von Nicht-Heap-Speicher ).

  • Arbeitsspeicher
    • Junge Generation
      • Eden Raum
      • Überlebender Raum
    • Alte Generation
      • Zehnjährige Generation
  • NonHeap-Speicher
    • Permanente Generation
    • Code Cache ( Ich glaube, "nur" von HotSpot Java VM aufgenommen)

Arbeitsspeicher

Der Heap-Speicher ist der Laufzeitdatenbereich, aus dem die Java VM Speicher für alle Klasseninstanzen und Arrays zuweist. Der Heap kann eine feste oder variable Größe haben. Der Garbage Collector ist ein automatisches Speicherverwaltungssystem, das den Heapspeicher für Objekte wiederherstellt.

Junge Generation

Junge Generation ist der Ort, an dem alle neuen Objekte entstehen. Wenn die junge Generation gefüllt ist, wird die Müllsammlung durchgeführt. Diese Speicherbereinigung heißt Minor GC. Young Generation ist in unter 2 Teile unterteilt

Eden Space: Der Pool, aus dem der Speicher für die meisten Objekte anfänglich zugewiesen wird.

Survivor Space: Der Pool enthält Objekte, die die Müllsammlung des Eden-Raums überlebt haben.

Alte Generation

Der Speicher der alten Generation enthält die Objekte, die nach vielen Runden von Minor GC langlebig sind und überlebt haben. Normalerweise wird die Speicherbereinigung im Speicher der alten Generation ausgeführt, wenn sie voll ist. Old Generation Garbage Collection heißt Major GC und dauert in der Regel länger. Die alte Generation enthält unter Teil:

Tenored space: Der Pool enthält Objekte, die seit einiger Zeit im Überlebendenraum existieren.

Nicht-Heap-Speicher

Nicht-Heap-Speicher enthält einen Methodenbereich, der von allen Threads und Speicher gemeinsam genutzt wird, der für die interne Verarbeitung oder Optimierung für die Java VM benötigt wird. Es speichert pro-Klassen-Strukturen wie eine Laufzeitkonstante Pool, Feld und Methode Daten und den Code für Methoden und Konstruktoren. Der Methodenbereich ist ein logischer Teil des Heapspeichers, aber abhängig von der Implementierung kann eine Java-VM diese nicht sammeln oder komprimieren. Wie der Heapspeicher kann der Methodenbereich eine feste oder variable Größe haben. Der Speicher für den Methodenbereich muss nicht zusammenhängend sein.

Permanente Generierung

Der Pool, der alle reflektierenden Daten der virtuellen Maschine selbst enthält, z. B. Klassen- und Methodenobjekte. Bei Java-VMs, die die gemeinsame Nutzung von Klassendaten verwenden, ist diese Generation in schreibgeschützte und schreibgeschützte Bereiche unterteilt.

Code-Cache

Die HotSpot Java VM enthält auch einen Code-Cache, der Speicher enthält, der zum Kompilieren und Speichern von nativem Code verwendet wird.

Beantworten der Fragen des OP speziell

  

Wo sind die Methoden von s gespeichert?

Nicht-Heap-Speicher - & gt; Permanente Generation

  

Hätte ich ein anderes Objekt von MemoryClass in myMethod erstellt, würde JVM   im Speicher des Speichers Speicher für die gleichen Methoden erneut zuweisen?

Stapelspeicher enthält nur lokale Variablen, so dass Ihre ORV (Objektreferenzvariable) von new MemoryClass immer noch im Stapelrahmen von myMethod erstellt würde, aber JVM würde nicht alle Methoden, Metadaten usw. von MemoryClass laden wieder in "Permanent Generation".

JVM lädt die Klasse nur einmal, und wenn sie die Klasse lädt, wird der Speicherplatz für die Klasse "Permanent Generation" zugewiesen und dies geschieht nur einmal, während die Klasse von JVM geladen wird.

  

Würde JVM den Speicher freigeben, der myMethod zugewiesen wurde, sobald er verfügbar ist   die Ausführung ist abgeschlossen, wenn ja, wie würde sie die Situation bewältigen   in Frage 2 erwähnt (gilt nur, wenn JVM Speicher zuweist   mehrmals zur selben Methode).

Stack-Rahmen, der für myMethod erstellt wurde, wird aus dem Stapelspeicher entfernt, so dass der gesamte für lokale Variablen erstellte Speicher bereinigt wird. Dies bedeutet jedoch nicht, dass JVM den in "Permanent Generation" für die Klasse reservierten Speicher bereinigt das Objekt, das Sie in myMethod

erstellt haben
  

Was wäre der Fall gewesen, wenn ich nur s erklärt hätte und nicht   initialisiere es, würde JVM noch allen Methoden Speicher zuweisen   java.lang.String-Klasse, wenn ja, warum?

Konkret gesprochen von String class, hätte JVM viel zu früh Platz für String in "Permanent Generation" reserviert, während JVM gestartet wird und ob Sie Ihre String-Variable initialisieren oder nicht, es spielt keine Rolle von " Permanente Generation "Perspektive.

Wenn wir von anderen benutzerdefinierten Klassen sprechen, würde JVM die Klasse laden und Speicher in "Permanent Generation" zuweisen, sobald Sie die Klasse definieren. Auch wenn Sie kein Objekt der Klasse erstellen, wird Speicher in " Permanent Generation "( Nicht-Heap-Bereich ) und wenn Sie ein Objekt der Klasse erstellen, wird Speicher in" Eden Space "( Heap-Bereich ) zugewiesen.

Quellen für obige Informationen und weitere Lektüre:

hagrawal 29.12.2016 15:44
quelle
1

Da die angenommene Antwort von arsy und die Antwort von hagrawal klar sind, wollen wir nur die vierte Frage näher ausführen:

  

Was wäre der Fall gewesen, wenn ich nur s erklärt hätte und nicht   initialisiere es, würde JVM noch allen Methoden Speicher zuweisen   java.lang.String-Klasse, wenn ja, warum?

Grundsätzlich gilt zwar, dass die Klassendaten - die die Informationen zu den Feldern und Methoden enthalten - in der permanenten Generation gespeichert sind (Metaraum ab JDK-8), es ist jedoch wichtig zu wissen, dass es die Objekte innerhalb des Java sind .lang.String-Klasse (z. B. char [], die alle Zeicheninformationen für diese Zeichenfolge enthält), für die Daten auf dem Heap reserviert sind.

Dies geschieht erst, wenn entweder ein neues String-Objekt erstellt wird - entweder mit dem Schlüsselwort 'new' oder durch ein neues String-Literal (zB: "helloworld").

    
Ravindra HV 29.12.2016 19:43
quelle