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:
MemoryClass
in myMethod
erstellt, würde JVM dann wieder Speicher für die gleichen Methoden im Stapelspeicher reservieren? 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) ). java.lang.String
class Speicher zuweisen, wenn ja, warum? 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.
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:
Lassen Sie mich zu Beginn diese 2 Diagramme mit JVM-Speicherbereichen einfügen:
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 ).
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 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.
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 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.
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.
Die HotSpot Java VM enthält auch einen Code-Cache, der Speicher enthält, der zum Kompilieren und Speichern von nativem Code verwendet wird.
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
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.
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").
Tags und Links java memory memory-management heap-memory stack-memory