0Pricing
Java Academy · Lección

Handles de downcall

Llame a funciones nativas

Handles de downcall es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.

Llamar a funciones nativas

Una llamada downcall es una llamada que va desde Java hacia el código nativo. FFM representa cada función nativa como un MethodHandle creado a partir de un Linker.

En esta lección se explica cómo buscar, describir e invocar una función C.

El enlazador nativo

Linker.nativeLinker() devuelve el enlazador correspondiente a la plataforma en ejecución. Conoce la convención de llamada de C y puede crear handles para funciones nativas.

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);
    }
}

Buscar un símbolo

Necesita la dirección de la función. linker.defaultLookup() busca en la biblioteca estándar de C; SymbolLookup.libraryLookup(name, arena) carga una biblioteca compartida específica.

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);
    }
}

Describir la firma

Un FunctionDescriptor describe la firma de C en términos de layouts. Para size_t strlen(const char*), el valor devuelto es un long y el argumento es un puntero (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);
    }
}

Crear el handle

Combine el símbolo y el descriptor con downcallHandle para obtener un MethodHandle que puede invocar como cualquier método de Java.

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());
    }
}

Invocar la función

Para llamar a strlen, debe pasar un puntero a una cadena nativa. Asigne la cadena en un Arena y, después, invoque el handle con invoke. El resultado se devuelve como un long de Java.

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);
        }
    }
}

Mapear tipos

Cada tipo de C se corresponde con un layout:

  • int se corresponde con ValueLayout.JAVA_INT
  • long/size_t se corresponden con JAVA_LONG
  • double se corresponde con JAVA_DOUBLE
  • Cualquier puntero se corresponde con ADDRESS

Es esencial que estas correspondencias sean correctas; de lo contrario, la llamada corromperá los datos.

Funciones que devuelven punteros

Cuando una función C devuelve un puntero, el handle devuelve un MemorySegment de longitud cero. Para leer más allá de su inicio, debe reinterpretarlo al tamaño correcto con reinterpret(byteSize).

Pasar muchos argumentos

FunctionDescriptor.of(returnLayout, arg1, arg2, ...) enumera los argumentos en orden. Para una función void, utilice FunctionDescriptor.ofVoid(args...) sin indicar un layout de retorno.

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);
    }
}

Gestionar errores con throws

Como MethodHandle.invoke declara throws Throwable, el método que lo llama debe gestionar la excepción o declararla. Por eso los ejemplos declaran throws Throwable.

Almacenar el handle en caché

Crear un handle downcall es relativamente costoso, por lo que debe hacerlo una sola vez y reutilizarlo. Un patrón habitual consiste en asignar el handle a un campo static final durante la inicialización de la clase e invocarlo muchas veces.

El propio handle es seguro para invocarse simultáneamente desde varios hilos.

Comprobación rápida

Recuerde cómo se describe un argumento puntero de C.

Resumen

Ha aprendido a llamar a funciones nativas:

  • Linker.nativeLinker() junto con un SymbolLookup para buscar símbolos
  • FunctionDescriptor describe la firma mediante layouts
  • downcallHandle produce un MethodHandle que puede invoke
  • Los punteros se corresponden con ADDRESS; invoke genera Throwable

A continuación: describir datos nativos complejos con layouts y estructuras.

Preguntas frecuentes

¿La lección «Handles de downcall» es gratis?

Sí — el texto completo de «Handles de downcall» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Handles de downcall»?

Llame a funciones nativas Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Java Academy?

No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Handles de downcall»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Java Academy?

Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Por qué FFM en lugar de JNI
  2. MemorySegment y Arena
  3. Handles de downcall
  4. Layouts y structs
← Volver a Java Academy