0Pricing
Java Academy · Lektion

Downcall Handles

Native Funktionen aufrufen

Downcall Handles ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Native Funktionen aufrufen

Ein Downcall ist ein Aufruf aus Java in nativen Code hinein. FFM stellt jede native Funktion als ein aus einem Linker erstelltes MethodHandle dar.

In dieser Lektion erfahren Sie, wie Sie eine C-Funktion finden, beschreiben und aufrufen.

Der native Linker

Linker.nativeLinker() gibt den Linker für die aktuell ausgeführte Plattform zurück. Er kennt die C-Aufrufkonvention und kann Handles für native Funktionen erzeugen.

import java.lang.foreign.Linker;

public class Main {
    public static void main(String[] args) {
        Linker linker = Linker.nativeLinker();
        System.out.println("Got native linker: " + linker);
    }
}

Ein Symbol finden

Sie benötigen die Adresse der Funktion. linker.defaultLookup() durchsucht die Standard-C-Bibliothek; SymbolLookup.libraryLookup(name, arena) lädt eine bestimmte gemeinsam genutzte Bibliothek.

import java.lang.foreign.*;

public class Main {
    public static void main(String[] args) {
        Linker linker = Linker.nativeLinker();
        SymbolLookup stdlib = linker.defaultLookup();
        MemorySegment addr = stdlib.find("strlen").orElseThrow();
        System.out.println("strlen address found: " + addr);
    }
}

Die Signatur beschreiben

Ein FunctionDescriptor beschreibt die C-Signatur anhand von Layouts. Bei size_t strlen(const char*) ist der Rückgabewert ein long und das Argument ein Zeiger (ADDRESS).

import java.lang.foreign.*;

public class Main {
    public static void main(String[] args) {
        FunctionDescriptor desc = FunctionDescriptor.of(
            ValueLayout.JAVA_LONG,   // return: size_t
            ValueLayout.ADDRESS);    // arg: const char*
        System.out.println("Descriptor: " + desc);
    }
}

Das Handle erstellen

Kombinieren Sie das Symbol und den Deskriptor mit downcallHandle, um ein MethodHandle zu erhalten, das Sie wie jede Java-Methode aufrufen können.

import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;

public class Main {
    public static void main(String[] args) {
        Linker linker = Linker.nativeLinker();
        MethodHandle strlen = linker.downcallHandle(
            linker.defaultLookup().find("strlen").orElseThrow(),
            FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));
        System.out.println("Handle ready: " + strlen.type());
    }
}

Die Funktion aufrufen

Um strlen aufzurufen, übergeben Sie einen Zeiger auf einen nativen String. Reservieren Sie den String in einer Arena und rufen Sie anschließend das Handle mit invoke auf. Das Ergebnis wird als Java-long zurückgegeben.

import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;

public class Main {
    public static void main(String[] args) throws Throwable {
        Linker linker = Linker.nativeLinker();
        MethodHandle strlen = linker.downcallHandle(
            linker.defaultLookup().find("strlen").orElseThrow(),
            FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment str = arena.allocateUtf8String("Hello, FFM");
            long len = (long) strlen.invoke(str);
            System.out.println("Length = " + len);
        }
    }
}

Typen abbilden

Jeder C-Typ wird auf ein Layout abgebildet:

  • int auf ValueLayout.JAVA_INT
  • long/size_t auf JAVA_LONG
  • double auf JAVA_DOUBLE
  • jeder Zeiger auf ADDRESS

Die korrekte Zuordnung ist entscheidend, andernfalls werden Daten durch den Aufruf beschädigt.

Funktionen, die Zeiger zurückgeben

Wenn eine C-Funktion einen Zeiger zurückgibt, liefert das Handle ein MemorySegment der Länge null. Um über dessen Anfang hinaus zu lesen, müssen Sie es mit reinterpret(byteSize) auf die richtige Größe neu interpretieren.

Viele Argumente übergeben

FunctionDescriptor.of(returnLayout, arg1, arg2, ...) listet die Argumente in der richtigen Reihenfolge auf. Für eine void-Funktion verwenden Sie FunctionDescriptor.ofVoid(args...) ohne Layout für den Rückgabewert.

import java.lang.foreign.*;

public class Main {
    public static void main(String[] args) {
        // int (*)(const char*, int)
        FunctionDescriptor two = FunctionDescriptor.of(
            ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_INT);
        // void (*)(int)
        FunctionDescriptor noReturn = FunctionDescriptor.ofVoid(ValueLayout.JAVA_INT);
        System.out.println(two + " / " + noReturn);
    }
}

Fehler im Handle mit throws behandeln

Da MethodHandle.invoke throws Throwable deklariert, muss Ihre aufrufende Methode die Ausnahme behandeln oder deklarieren. Deshalb deklarieren die Beispiele throws Throwable.

Das Handle zwischenspeichern

Das Erstellen eines Downcall-Handles ist relativ aufwendig. Erstellen Sie es daher einmal und verwenden Sie es wieder. Ein häufig verwendetes Muster besteht darin, das Handle während der Klasseninitialisierung in einem Feld static final zu binden und es viele Male aufzurufen.

Das Handle selbst ist für gleichzeitige Aufrufe durch mehrere Threads thread-sicher.

Kurzer Test

Rufen Sie sich ins Gedächtnis, wie ein C-Zeigerargument beschrieben wird.

Zusammenfassung

Sie haben gelernt, native Funktionen aufzurufen:

  • Linker.nativeLinker() zusammen mit einem SymbolLookup, um Symbole zu finden
  • FunctionDescriptor beschreibt die Signatur anhand von Layouts
  • downcallHandle liefert ein MethodHandle, das Sie mit invoke aufrufen
  • Zeiger werden auf ADDRESS abgebildet; invoke löst Throwable aus

Als Nächstes: komplexe native Daten mit Layouts und Strukturen beschreiben.

Häufig gestellte Fragen

Ist die Lektion „Downcall Handles“ kostenlos?

Ja — der vollständige Text von „Downcall Handles“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Downcall Handles“?

Native Funktionen aufrufen Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Java Academy zu starten?

Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Downcall Handles“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?

Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Warum FFM statt JNI
  2. MemorySegment und Arena
  3. Downcall Handles
  4. Layouts und Structs
← Zurück zu Java Academy