Handles de downcall
Chame funções nativas.
Handles de downcall é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
Chamando funções nativas
Uma chamada descendente é uma chamada do Java para dentro do código nativo. FFM representa cada função nativa como um MethodHandle criado a partir de um Linker.
Esta lição mostra como encontrar, descrever e invocar uma função C.
O vinculador nativo
Linker.nativeLinker() retorna o vinculador da plataforma em execução. Ele conhece a convenção de chamada C e pode produzir identificadores para funções 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);
}
}Encontrando um símbolo
Você precisa do endereço da função. linker.defaultLookup() pesquisa a biblioteca C padrão; SymbolLookup.libraryLookup(name, arena) carrega uma biblioteca compartilhada 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);
}
}Descrevendo a assinatura
Um FunctionDescriptor descreve a assinatura C em termos de descrições. Para size_t strlen(const char*), o retorno é um inteiro longo e o argumento é um ponteiro (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);
}
}Criando o identificador
Combine o símbolo e a descrição com downcallHandle para obter um MethodHandle que você pode invocar como qualquer método 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());
}
}Invocando a função
Para chamar strlen, passe um ponteiro para uma cadeia de caracteres nativa. Aloque a cadeia em uma arena e depois invoke o identificador. O resultado retorna como um inteiro longo 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);
}
}
}Mapeando tipos
Cada tipo C corresponde a uma descrição:
intparaValueLayout.JAVA_INTlong/size_tparaJAVA_LONGdoubleparaJAVA_DOUBLE- qualquer ponteiro para
ADDRESS
Fazer essas correspondências corretamente é essencial; caso contrário, a chamada corromperá os dados.
Funções que retornam ponteiros
Quando uma função C retorna um ponteiro, o identificador retorna um MemorySegment de tamanho zero. Para ler além do início, você precisa reinterpretá-lo para o tamanho correto com reinterpret(byteSize).
Passando vários argumentos
FunctionDescriptor.of(returnLayout, arg1, arg2, ...) lista os argumentos na ordem. Para uma função void, use FunctionDescriptor.ofVoid(args...) sem uma descrição 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);
}
}Lidando com erros usando uma declaração de exceção
Como MethodHandle.invoke declara throws Throwable, o método que o chama precisa tratar ou declarar isso. É por isso que os exemplos declaram throws Throwable.
Armazenando o identificador em cache
Criar um identificador de chamada descendente é relativamente caro, portanto faça isso uma vez e reutilize-o. Um padrão comum é vincular o identificador a um campo static final durante a inicialização da classe e invocá-lo muitas vezes.
O identificador em si é seguro para chamadas concorrentes.
Verificação rápida
Lembre-se de como um argumento ponteiro C é descrito.
Recapitulação
Você aprendeu a chamar funções nativas:
Linker.nativeLinker()junto com umSymbolLookuppara encontrar símbolosFunctionDescriptordescreve a assinatura com descriçõesdowncallHandlefornece umMethodHandleque vocêinvoke- Ponteiros correspondem a
ADDRESS;invokegeraThrowable
A seguir: descrever dados nativos complexos com descrições e estruturas.
Perguntas Frequentes
A aula “Handles de downcall” é grátis?
Sim — o texto completo de “Handles de downcall” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “Handles de downcall”?
Chame funções nativas. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Handles de downcall”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Por que FFM em vez de JNI
- MemorySegment e Arena
- Handles de downcall
- Layouts e structs