[Java] Nativen (Off-Heap) Speicher allozieren

Ja, ihr habt richtig gelesen! In diesem Blog Beitrag geht es darum, wie man in Java nativen Speicher (Off Heap Speicher) alloziert, der außerhalb des Garbage Collectors läuft, also in etwa so, wie wenn man in C oder C++ mit malloc() Speicher allozieren würde.

 

Dazu gibt es in Java 2 Möglichkeiten:

 

Ich will euch in diesem Artikel beide Varianten näher bringen.

 

1. sun.misc.Unsafe

sun.misc.Unsafe ist eine mittlerweile veraltete Api (sollte ursprünglich aus Java 9 entfernt werden), die immer noch sehr oft benutzt wird, vorallem von OpenGL Anwendungen unter Java, um native Pointer übergeben zu können (z.B. bei der library LWJGL) oder performant Speicher verwalten zu können, der nicht vom Garbage Collector verwaltet wird. Aber genug der langen Worte, lasst uns nativen Speicher für 4 Integer allozieren!

Zuerst benötigen wir die (Singleton) Instanz von Unsafe, hierfür ist ein kleiner Trick erforderlich:

 

Als nächstes benötigen wir eine kleine Hilfsmethode, um die Speicheradressen leichter berechnen zu können:

 

In diesem Beispiel wollen wir einmal nativen Speicher allozieren, der Platz für 4 Integer bietet:

 

Am Anfang allozieren wir mit unsafe.allocateMemory(numberOfBytes) nativen Speicher, beschreiben diesen mit putInt(), lesen ihn mit getInt() und gegen den Speicher am Ende wieder mit unsafe.freeMemory(startIndex) frei.

 

Nachteile dieser Variante:

  • Wenn der Programmierer nicht mehr dran denkt, den Speicher freizugeben, bleibt dieser im RAM reserviert, bis das Programm geschlossen wird. Es greift kein Garbage Collector ein
  • sun.misc.Unsafe ist in Java 8 bereits als deprecated markiert

 

Vorteile dieser Variante:

  • man erzeugt weniger Garbage Pressure –> der Garbage Collector muss nicht so oft laufen
  • man kann an native C / C++ libraries mittels JNI (Java Native Interface) direkt die Speicheradresse übergeben und muss keine Werte kopieren
  • performanter

 

Warum soll sun.misc.Unsafe überhaupt entfernt werden?

sun.misc.Unsafe war ursprünglich lediglich als interne Api gedacht (die JVM / JDK selbst) und nicht für Entwickler, die diese ebenfalls nutzen. Aus diesem Grund ist es auch so kompliziert, überhaupt an die Unsafe Instanz zu kommen.

“The methods in this class can be used to access memory inside and outside of Java’s heap with direct pointers. As there are no checks, they could be used to crash the JVM (SIGSEGV) or to inject platform’s assembly code into the JVM! This is generally “unsafe” (as the name of the class suggests). Java code should use the “official” APIs provided by the JDK: AtomicInteger, ConcurrentHashMap, ByteBuffer,…” – Quelle: https://jaxenter.com/javas-unsafe-class-there-is-certainly-also-a-way-without-it-119084.html

 

Auch wenn sun.misc.Unsafe bereits als deprecated markiert und ursprünglich aus Java 9 entfernt werden sollte, wird es sun.misc.Unsafe wohl doch noch ne Weile geben. Der Grund ist, dass es 1. keine effizientere Methode derzeit in Java gibt und 2. so viele Libraries auf sun.misc.Unsafe setzen, dass ein Entfernen aus dem JDK zu vielen Inkompatibilitäten führen würde.

Einige interessante Artikel zu diesem Thema:

 

2. Die neue ByteBuffer Api

Kommen wir nun zu der 2. Variante, der ByteBuffer Api. Diese Api wurde mit Java 7 eingeführt und hat einen entscheidenden Unterschied:
Der Speicher liegt zwar Off Heap, ist also nativer Speicher, aber die Referenz dieses Speichers wird weiterhin vom Garbage Collector verwaltet.

 

Dies hat im Gegensatz zu sun.misc.Unsafe einige Nachteile:

  • Der Garbage Collector verwaltet immerhin noch die Speicheradresse (1 long)
  • Man kann den Speicher nur über einen Trick manuell wieder direkt freigeben

 

Dafür gibts aber auch einige Vorteile:

  • Der Garbage Collector kann anhand der Referenz weiterhin erkennen, ob der Speicherblock noch benutzt wird oder nicht und den Speicher dann entsprechend freigeben
  • es ist kein direktes Einschleusen von Code mehr in die JVM (Java Virtual Machine) möglich –> entspricht mehr dem Java Sicherheitskonzept

 

Als erstes benötigen wir 2 kleine Hilfsmethoden:

 

Nun zum Code:

 

Falls ihr noch Fragen, Kritik oder Anmerkungen habt – schreibt es in die Kommentare! 😀

Und wenn euch dieser Artikel gefallen hat, könnt ihr ihn auch gerne weiter empfehlen! 😀

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.