{"id":640,"date":"2026-01-18T00:49:31","date_gmt":"2026-01-17T23:49:31","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=640"},"modified":"2026-02-16T00:57:24","modified_gmt":"2026-02-15T23:57:24","slug":"die-foreign-function-memory-api-in-java-22-native-performance-ohne-jni","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=640","title":{"rendered":"Die Foreign Function &amp; Memory API in Java 22 \u2013 Native Performance ohne JNI"},"content":{"rendered":"\n<p>Mit der Ver\u00f6ffentlichung von <strong>Java 22<\/strong> hat die <strong>Foreign Function &amp; Memory (FFM) API<\/strong> endg\u00fcltig den Status einer stabilen, produktionsreifen Schnittstelle erreicht. Sie erm\u00f6glicht es Java-Entwickler:innen, auf einfache, sichere und performante Weise auf native Bibliotheken und Speicherbereiche au\u00dferhalb der Java-Heap-Struktur zuzugreifen. Damit l\u00f6st sie teilweise das traditionelle <strong>Java Native Interface (JNI)<\/strong> ab, das lange Zeit der Standardweg f\u00fcr die Interaktion mit C- oder C++-Code war. In diesem Artikel beleuchten wir die Kernkonzepte der FFM-API, zeigen praxisnahe Beispiele und vergleichen sie eingehend mit JNI.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Grundlagen der Foreign Function &amp; Memory API<\/h2>\n\n\n\n<p>Die FFM-API verfolgt zwei zentrale Ziele:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Native Funktionen aufrufen<\/strong>: Java-Code kann Methoden aus nativen Bibliotheken aufrufen, ohne auf komplexe JNI-Schnittstellen angewiesen zu sein.<\/li>\n\n\n\n<li><strong>Memory Management au\u00dferhalb des Heaps<\/strong>: Entwickler:innen k\u00f6nnen Speicherbereiche erstellen, lesen, schreiben und wieder freigeben, die au\u00dferhalb der von der JVM verwalteten Heap-Struktur liegen.<\/li>\n<\/ol>\n\n\n\n<p>Die FFM-API arbeitet dabei haupts\u00e4chlich mit drei Bausteinen:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>MemorySegment<\/code><\/strong>: Repr\u00e4sentiert einen zusammenh\u00e4ngenden Speicherbereich, vergleichbar mit einem Zeiger auf ein Array in C.<\/li>\n\n\n\n<li><strong><code>MemoryAddress<\/code><\/strong>: Stellt eine konkrete Adresse im Speichersegment dar.<\/li>\n\n\n\n<li><strong><code>CLinker<\/code> und <code>FunctionDescriptor<\/code><\/strong>: Helfen beim Mapping von Java-Typen auf native Funktionssignaturen.<\/li>\n<\/ul>\n\n\n\n<p>Ein zentrales Konzept ist die <strong>Sicherheitskontrolle<\/strong>: Im Gegensatz zu JNI sorgt die FFM-API daf\u00fcr, dass Speicherlecks und Speicherverletzungen reduziert werden, indem Segmentgrenzen und Typen strikt gepr\u00fcft werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ein einfaches Beispiel: Aufruf einer C-Funktion<\/h2>\n\n\n\n<p>Angenommen, wir haben eine C-Bibliothek mit folgender Funktion:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ mathlib.c<\/span>\nint add(int a, int b) {\n    <span class=\"hljs-keyword\">return<\/span> a + b;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Der klassische JNI-Ansatz w\u00fcrde zun\u00e4chst das Erstellen von Header-Dateien, das Schreiben einer nativen Implementierung in C und das Kompilieren der Bibliothek erfordern. Anschlie\u00dfend m\u00fcsste Java die <code>System.loadLibrary<\/code>-Methode aufrufen und die nativen Methoden deklarieren:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">JNIMath<\/span> <\/span>{\n    <span class=\"hljs-keyword\">static<\/span> { System.loadLibrary(<span class=\"hljs-string\">\"mathlib\"<\/span>); }\n    <span class=\"hljs-keyword\">public<\/span> native int add(int a, int b);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Mit der <strong>FFM-API<\/strong> in Java 22 geht das wesentlich direkter und ohne Boilerplate-Code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> java.lang.foreign.*;\n<span class=\"hljs-keyword\">import<\/span> java.lang.invoke.*;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">FFMMath<\/span> <\/span>{\n    public <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> main(<span class=\"hljs-built_in\">String<\/span>&#91;] args) throws Throwable {\n        System.loadLibrary(<span class=\"hljs-string\">\"mathlib\"<\/span>);\n\n        SymbolLookup lib = SymbolLookup.libraryLookup(<span class=\"hljs-string\">\"mathlib\"<\/span>, SymbolLookup.loaderLookup());\n        MethodHandle add = CLinker.systemCLinker()\n            .downcallHandle(\n                lib.lookup(<span class=\"hljs-string\">\"add\"<\/span>).get(),\n                MethodType.methodType(int.class, int.class, int.class),\n                FunctionDescriptor.of(CLinker.C_INT, CLinker.C_INT, CLinker.C_INT)\n            );\n\n        int result = (int) add.invokeExact(<span class=\"hljs-number\">5<\/span>, <span class=\"hljs-number\">7<\/span>);\n        System.out.println(<span class=\"hljs-string\">\"5 + 7 = \"<\/span> + result);\n    }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Hierbei \u00fcbernimmt <strong>FFM<\/strong> die Typenpr\u00fcfung, die korrekte Konvertierung zwischen Java- und C-Typen sowie das Exception-Handling auf nativer Ebene, was den Code wesentlich sicherer und wartbarer macht.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Arbeit mit nativen Speicherbereichen<\/h2>\n\n\n\n<p>Neben dem Funktionsaufruf bietet die FFM-API auch komfortable Werkzeuge f\u00fcr den Umgang mit Speicher au\u00dferhalb des Java-Heaps:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">try<\/span> (MemorySegment segment = MemorySegment.allocateNative(<span class=\"hljs-number\">4<\/span> * Integer.BYTES)) {\n    VarHandle intHandle = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder());\n    <span class=\"hljs-keyword\">for<\/span> (int i = <span class=\"hljs-number\">0<\/span>; i &lt; <span class=\"hljs-number\">4<\/span>; i++) {\n        intHandle.set(segment, i * Integer.BYTES, i + <span class=\"hljs-number\">1<\/span>);\n    }\n\n    <span class=\"hljs-keyword\">for<\/span> (int i = <span class=\"hljs-number\">0<\/span>; i &lt; <span class=\"hljs-number\">4<\/span>; i++) {\n        int value = (int) intHandle.get(segment, i * Integer.BYTES);\n        System.out.println(<span class=\"hljs-string\">\"Wert an Position \"<\/span> + i + <span class=\"hljs-string\">\": \"<\/span> + value);\n    }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Mit <code>MemorySegment.allocateNative<\/code> wird ein nativer Speicherblock alloziert, der nach Verlassen des <code>try-with-resources<\/code>-Blocks automatisch freigegeben wird. So entf\u00e4llt das manuelle Freeen des Speichers, wie es bei JNI erforderlich w\u00e4re.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Vergleich FFM vs. JNI<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Boilerplate und Lesbarkeit<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>JNI<\/strong> erfordert Header-Generierung, explizite <code>native<\/code>-Methoden, manuelles Kompilieren von C\/C++-Code und sorgf\u00e4ltiges Memory Management.<\/li>\n\n\n\n<li><strong>FFM<\/strong> erlaubt direkte Definitionen von MethodHandles, Symbol-Lookups und nativen Speicherzugriffen innerhalb von Java selbst. Der Code ist k\u00fcrzer, klarer und einfacher zu warten.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. Sicherheit<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>JNI<\/strong> ist anf\u00e4llig f\u00fcr Speicherlecks, Buffer-Overflows und typbedingte Fehler.<\/li>\n\n\n\n<li><strong>FFM<\/strong> arbeitet mit <strong>MemorySegments<\/strong> und VarHandles, die Bounds-Checks und Typ\u00fcberpr\u00fcfungen automatisch durchf\u00fchren. Das Risiko von Segmentation Faults wird reduziert.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3. Performance<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>JNI<\/strong> hat eine geringe, aber sp\u00fcrbare Overhead-Schicht, da die JVM und der native Code \u00fcber Br\u00fccken kommunizieren.<\/li>\n\n\n\n<li><strong>FFM<\/strong> ist ebenfalls sehr performant und erlaubt Compiler-Optimierungen wie Inlining von Funktionsaufrufen. Bei manchen Workloads kann es sogar schneller sein, weil weniger Boilerplate ausgef\u00fchrt wird.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4. Wartbarkeit<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>JNI<\/strong> erfordert Synchronisierung zwischen Java- und C-Code, was bei \u00c4nderungen in der nativen Bibliothek zu Kompatibilit\u00e4tsproblemen f\u00fchren kann.<\/li>\n\n\n\n<li><strong>FFM<\/strong> erlaubt, dank deklarativer <code>FunctionDescriptor<\/code>-Typen, eine klarere Spezifikation der Schnittstellen, die leichter zu refaktorieren sind.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">5. Speicherverwaltung<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>JNI<\/strong>: Entwickler:innen m\u00fcssen Speicher manuell freigeben (<code>malloc<\/code>\/<code>free<\/code>) und auf Garbage Collection achten.<\/li>\n\n\n\n<li><strong>FFM<\/strong>: Automatisches Schlie\u00dfen von <code>MemorySegment<\/code> via <code>try-with-resources<\/code> reduziert das Risiko von Speicherlecks erheblich.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Praktische Anwendungsbereiche<\/h2>\n\n\n\n<p>Die FFM-API eignet sich besonders f\u00fcr:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Hochperformante Numerik, z.\u202fB. KI- oder Bildverarbeitungsbibliotheken in C\/C++.<\/li>\n\n\n\n<li>Zugriff auf Systembibliotheken, z.\u202fB. POSIX-Funktionen oder Windows-APIs.<\/li>\n\n\n\n<li>Interaktion mit bestehendem Legacy-Code, ohne JNI-Wrapper schreiben zu m\u00fcssen.<\/li>\n\n\n\n<li>Low-Level-Netzwerkprogrammierung oder Speicherpuffer-Verwaltung f\u00fcr I\/O-intensive Anwendungen.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Fazit<\/h2>\n\n\n\n<p>Die <strong>Foreign Function &amp; Memory API<\/strong> in Java 22 stellt einen bedeutenden Fortschritt gegen\u00fcber JNI dar. Sie vereinfacht die Nutzung nativer Funktionen, erh\u00f6ht die Sicherheit beim Speicherzugriff und macht den Code leichter wartbar. W\u00e4hrend JNI weiterhin existiert und in bestimmten Legacy-Szenarien unverzichtbar ist, empfiehlt sich f\u00fcr neue Projekte der FFM-Ansatz, da er eine moderne, klar typisierte und speichersichere Alternative bietet.<\/p>\n\n\n\n<p>Durch die Kombination aus MethodHandles, MemorySegments und deklarativen FunctionDescriptors bietet die FFM-API eine flexible und performante M\u00f6glichkeit, Java und native Bibliotheken effizient zu verbinden \u2013 ohne die Komplexit\u00e4t und Fehleranf\u00e4lligkeit des traditionellen JNI-Ansatzes.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mit der Ver\u00f6ffentlichung von Java 22 hat die Foreign Function &amp; Memory (FFM) API endg\u00fcltig den Status einer stabilen, produktionsreifen Schnittstelle erreicht. Sie erm\u00f6glicht es Java-Entwickler:innen, auf einfache, sichere und performante Weise auf native Bibliotheken und Speicherbereiche au\u00dferhalb der Java-Heap-Struktur zuzugreifen. Damit l\u00f6st sie teilweise das traditionelle Java Native Interface (JNI) ab, das lange Zeit [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-640","post","type-post","status-publish","format-standard","hentry","category-plain_java"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/640","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=640"}],"version-history":[{"count":2,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/640\/revisions"}],"predecessor-version":[{"id":643,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/640\/revisions\/643"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=640"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=640"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=640"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}