Ist Off-Heap-Speicher dasselbe wie Stack-Speicher?

vish234

Mitglied
Ich verstehe den Unterschied zwischen Stack- und Heap-Speicher, bin aber in mehreren Blogs auf den Begriff Off-Heap-Speicher gestoßen. Ich habe mir viele YouTube-Videos angesehen, um zu sehen, ob es einen Zusammenhang zwischen Off-Heap-Speicher und Stack-Speicher gibt. Gemäß den allgemeinen Antworten zu diesem Thema von scaler topics bezieht sich Off-Heap-Speicher auf Speicherelemente, die von EHCache verwaltet werden und nicht der Garbage Collection unterliegen. Dieses Konzept ist in Ordnung, aber mein Problem ist, ob Off-Heap-Speicher dasselbe wie Stack-Speicher oder eine separate Sache in der Speicherverwaltung ist.
PS: Wenn sie nicht gleich sind, könnte jemand freundlicherweise erklären, was sie im Detail mit einer grundlegenden Erklärung unterscheidet? Ich lerne immer noch etwas über die Java-Speicherverwaltung.

Moderator Edit: Link zu scaler topics gelöscht (Spam).
 
Zuletzt bearbeitet von einem Moderator:
"off-heap" in java Kontext (gerade bei NIO) bedeutet, dass es sich hier um Speicher handelt, der nicht von der VM verwaltet wird, also wo z.B. Keine Java Objekte liegen.
Der Speicher ist einfach nur anderer Speicher im Speicherraum des JVM Prozesses. Zum Beispiel ein memory mapped file.
 
Vielleicht noch etwas ausführlicher, weil ich gerade Lust/Zeit habe:

Die JVM spezifiziert eine eigene virtuelle Maschine durch die Java Virtual Machine Specification (JVMS).

Hier bedeutet der "Stack" jener Speicherbereich, welcher jeweils pro Thread existiert, um "Frames" für Methodenaufrufe (als LIFO- also "Stack"-Datenstruktur) zu verwalten: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.2

Die JVMS macht auch eine Referenz auf "native" bzw. "C" Stacks für die Unterstützung von "native" methods: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.6
Da "native" methods ja keine Java-Methoden sind, sondern durch nativen Code (also direkten Code des physischen Prozessors, auf dem die Java Virtual Machine aufsetzt) implementiert ist, benötigt dieser native Code auch eine Laufzeitumgebung, bzw. zumindest mal einen Hardware-Stack (wenn das von der physischen Maschine unterstützt wird).

Der Begriff "Heap" bedeutet im Kontext dieser Java virtuellen Maschine jener Speicherbereich, der für das Anlegen von Objekten und Arrays reserviert ist und über alle Threads geteilt wird: https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-2.html#jvms-2.5.3

Es gibt nun den Begriff "on-heap" und "off-heap" im Java Kontext.

"on-heap" bedeutet eben genau der Heap, den ich oben angesprochen hatte. Also der "Heap" Speicher der JVM.

"off-heap" bedeutet jener Speicherbereich, der weder JVM-Stack noch JVM-Heap ist. Dieser Art von Speicher wurde für die Interoperabilität/Interop mit nativem Code spätestens seit Einführung der "New I/O" (bzw. kurz "NIO") in Java 1.4 wichtig. Mit dem ByteBuffer gab es nun das erste Mal überhaupt die Möglichkeit, per standardisierter Java API auf Speicherbereiche zuzugreifen, die nicht der Java Heap ist, um z.B. Speicher zwischen einer Java-Anwendung und einer nativen Library effizient zu kommunizieren. Vorher war diese Kommunikation zwar auch möglich, allerdings nur mit JNI Code und explizitem "Pinning" von "on-heap" Speicher, damit etwa der Garbage Collector den Speicher (der in den meisten Fällen zu einem primitiven Java Array gehörte - also wieder einem Java Objekt) nicht "verschiebt".

Mit NIO war es nun möglich, innerhalb von Java einfach mal "off-heap" Speicher zu alloziieren und zu verwenden (lesen/schreiben) bzw. woanders weiterzureichen (z.B. zu einer Schnittstelle einer nativen Library).
Desweiteren besteht mit JNI (welche mit Java 1.4 um einige Funktionen erweitert wurde) auch die Möglichkeit, einen ByteBuffer an Java zu zurückzugeben, der auf eine beliebige Speicheradresse zeigt und eine beliebige Kapazität hat. Dieser Speicherbereich kann theoretisch auch auf den "nativen Stack" bzw. "C Stack" des JVM Prozesses zeigen. Hier kann einfach eine beliebige Adresse verwendet werden.

Dies ermöglichte nun auch, Speicher, der nicht initial von deinem Java-Prozess (per ByteBuffer.allocateDirect()) alloziiert wurde, sondern von einer nativen Library, innerhalb deiner Java Anwendung über die ByteBuffer API zu lesen/schreiben.
 

Zurück
Oben