statische Zuordnung in Java - Heap, Stack und permanente Generierung

117

Ich habe in letzter Zeit viel über Speicherzuweisungsschemata in Java gelesen, und es gab viele Zweifel, als ich aus verschiedenen Quellen gelesen habe. Ich habe meine Konzepte gesammelt und möchte Sie bitten, alle Punkte durchzugehen und sie zu kommentieren. Ich habe erfahren, dass die Speicherzuweisung JVM-spezifisch ist, daher muss ich vorher sagen, dass meine Frage Sun-spezifisch ist.

  1. Klassen (von den Klassenladern geladen) befinden sich in einem speziellen Bereich auf dem Heap: Permanent Generation
  2. Alle Informationen zu einer Klasse wie der Name der Klasse, die der Klasse zugeordneten Objektarrays, die von JVM verwendeten internen Objekte (wie Java / Lang / Object) und die Optimierungsinformationen werden in den Bereich Permanente Generierung übernommen.
  3. Alle statischen Elementvariablen werden wieder im Bereich Permanente Generierung gespeichert.
  4. Objekte gehen auf einen anderen Haufen: Junge Generation
  5. Es gibt nur eine Kopie jeder Methode pro Klasse, sei es die statische oder die nicht statische Methode. Diese Kopie wird in den Bereich Permanent Generation gestellt. Bei nicht statischen Methoden werden alle Parameter und lokalen Variablen auf den Stapel übertragen. Wenn diese Methode konkret aufgerufen wird, wird ein neuer Stapelrahmen zugeordnet. Ich bin nicht sicher, wo die lokalen Variablen einer statischen Methode gespeichert sind. Sind sie auf dem Haufen der permanenten Generation? Oder nur ihre Referenz wird im Bereich der permanenten Generierung gespeichert, und die eigentliche Kopie befindet sich an einer anderen Stelle (wo?)
  6. Ich bin mir auch nicht sicher, wo der Rückgabetyp einer Methode gespeichert wird.
  7. Wenn die Objekte (in der jungen Generation) ein statisches Element (in der permanenten Generation) verwenden müssen, erhalten sie einen Verweis auf das statische Element und erhalten genügend Speicherplatz, um den Rückgabetyp der Methode usw. Zu speichern.

Vielen Dank, dass Sie das durchgemacht haben!

Jaguar
quelle

Antworten:

152

Erstens, wie Ihnen inzwischen klar sein sollte, dass es nur sehr wenige Menschen gibt, die diese Antworten aus erster Hand bestätigen können. Nur sehr wenige Leute haben an aktuellen HotSpot-JVMs gearbeitet oder sie so gründlich studiert, dass sie wirklich bekannt sind. Die meisten Leute hier (ich eingeschlossen) antworten auf der Grundlage von Dingen, die sie an anderer Stelle geschrieben haben oder auf die sie geschlossen haben. Normalerweise basiert das, was hier oder in verschiedenen Artikeln und Webseiten geschrieben wird, auf anderen Quellen, die möglicherweise endgültig sind oder nicht. Oft ist es vereinfacht, ungenau oder einfach falsch.

Wenn Sie eine endgültige Bestätigung Ihrer Antworten wünschen, müssen Sie den OpenJDK-Quellcode wirklich herunterladen ... und Ihre eigenen Recherchen durchführen, indem Sie den Quellcode lesen und verstehen. Fragen zu SO zu stellen oder zufällige Webartikel zu durchsuchen, ist keine solide akademische Forschungstechnik.

Trotzdem ...

... meine Frage ist sonnenspezifisch.

Zu dem Zeitpunkt, als diese Frage gestellt wurde, hatte Sun Microsystems aufgehört zu existieren. Die Frage war daher Oracle-spezifisch. AFAIK, alle aktuellen (nicht forschenden) JVM-Implementierungen von Drittanbietern sind entweder direkte Ports einer OpenJDK-Version oder stammen von einer anderen Sun / Oracle-Version ab.

Die folgenden Antworten gelten für Oracle Hotspot- und OpenJDK-Versionen und wahrscheinlich auch für die meisten anderen ... einschließlich GraalVM.

1) Klassen (von den Klassenladern geladen) befinden sich in einem speziellen Bereich auf dem Heap: Permanent Generation.

Vor Java 8 ja.

Ab Java 8 wurde der PermGen-Bereich durch Metaspace ersetzt. Geladene und JIT-kompilierte Klassen gehen jetzt dorthin. PermGen existiert nicht mehr.

2) Alle Informationen zu einer Klasse wie der Name der Klasse, die der Klasse zugeordneten Objektarrays, die von JVM verwendeten internen Objekte (wie Java / Lang / Object) und die Optimierungsinformationen werden in den Bereich Permanente Generierung übernommen.

Mehr oder weniger ja. Ich bin mir nicht sicher, was du mit einigen dieser Dinge meinst. Ich vermute, dass "interne Objekte, die von JVM verwendet werden (wie Java / Lang / Object)" JVM-interne Klassendeskriptoren bedeuten.

3) Alle statischen Elementvariablen werden wieder im Bereich der permanenten Generierung gespeichert.

Die Variablen selbst ja. Diese Variablen (wie alle Java-Variablen) enthalten entweder primitive Werte oder Objektreferenzen. Während sich die statischen Elementvariablen in einem Frame befinden, der im Permgen-Heap zugewiesen ist, können die Objekte / Arrays, auf die diese Variablen verweisen, in einem beliebigen Heap zugewiesen werden .

4) Objekte gehen auf einen anderen Haufen: Junge Generation

Nicht unbedingt. Große Objekte können direkt der festen Generation zugeordnet werden.

5) Es gibt nur eine Kopie jeder Methode pro Klasse, sei es die statische oder die nicht statische Methode. Diese Kopie wird in den Bereich Permanent Generation gestellt.

Angenommen, Sie beziehen sich auf den Code der Methode, dann AFAIK ja. Es kann jedoch etwas komplizierter sein. Beispielsweise kann dieser Code zu unterschiedlichen Zeiten während des Lebens der JVM in Form von Bytecode und / oder nativem Code vorliegen.

... Bei nicht statischen Methoden werden alle Parameter und lokalen Variablen auf den Stapel übertragen - und wenn diese Methode konkret aufgerufen wird, wird ein neuer Stapelrahmen zugeordnet.

Ja.

... Ich bin nicht sicher, wo die lokalen Variablen einer statischen Methode gespeichert sind. Sind sie auf dem Haufen der permanenten Generation? Oder nur ihre Referenz wird im Bereich der permanenten Generierung gespeichert, und die eigentliche Kopie befindet sich an einer anderen Stelle (wo?)

Nein. Sie werden wie lokale Variablen in nicht statischen Methoden auf dem Stapel gespeichert.

6) Ich bin mir auch nicht sicher, wo der Rückgabetyp einer Methode gespeichert wird.

Wenn Sie den Wert meinen, der von einem (nicht ungültigen) Methodenaufruf zurückgegeben wird, wird er entweder auf dem Stapel oder in einem Maschinenregister zurückgegeben. Wenn es auf dem Stapel zurückgegeben wird, dauert es je nach Rückgabetyp ein oder zwei Wörter.

7) Wenn die Objekte (in der jungen Generation) ein statisches Element (in der permanenten Generation) verwenden müssen, erhalten sie einen Verweis auf das statische Element und erhalten genügend Speicherplatz, um den Rückgabetyp der Methode usw. Zu speichern .

Das ist ungenau (oder zumindest drücken Sie sich nicht klar aus).

Wenn eine Methode auf eine statische Elementvariable zugreift, wird entweder ein primitiver Wert oder eine Objektreferenz abgerufen . Dies kann einer (vorhandenen) lokalen Variablen oder einem (vorhandenen) lokalen Parameter zugewiesen, einem (vorhandenen) statischen oder nicht statischen Element zugewiesen, einem (vorhandenen) Element eines zuvor zugewiesenen Arrays zugewiesen oder einfach verwendet und verworfen werden.

  • In keinem Fall muss neuer Speicher zugewiesen werden, um entweder eine Referenz oder einen primitiven Wert zu enthalten.

  • In der Regel reicht ein Speicherwort aus, um eine Objekt- oder Arrayreferenz zu speichern, und ein primitiver Wert belegt je nach Hardwarearchitektur in der Regel ein oder zwei Wörter.

  • In keinem Fall muss der Aufrufer Speicherplatz zuweisen, um ein von einer Methode zurückgegebenes Objekt / Array aufzunehmen. In Java werden Objekte und Arrays immer mithilfe der Pass-by-Value-Semantik zurückgegeben. Der zurückgegebene Wert ist jedoch eine Objekt- oder Array-Referenz.


Weitere Informationen finden Sie in den folgenden Ressourcen:

Stephen C.
quelle