Learn · concepts

O que é JNI? Interface Nativa Java para Modders

A JNI (Java Native Interface) é a ponte nativa do Java para chamar C/C++ a partir da JVM e vice-versa. É a forma padrão como um mod do Minecraft carrega uma biblioteca nativa.

TRtrolPublished 6 min read

O que é JNI em termos simples?

JNI (Java Native Interface) é a parte do Java que conecta dois mundos: bytecode gerenciado na JVM e código de máquina compilado escrito em C ou C++. Um método recebe a palavra-chave native e nenhum corpo, e em tempo de execução a JVM o vincula a uma função correspondente em uma biblioteca nativa carregada. A partir daí, ambos os lados trocam argumentos e valores de retorno.

A fronteira não é unidirecional. A função nativa recebe um ponteiro JNIEnv, e esse identificador é o portal de volta para o Java: ele expõe chamadas para leitura e escrita de campos Java, invocação de métodos Java, construção de objetos e lançamento de exceções. Assim, a mesma ponte que permite ao Java chamar para fora também permite ao C chamar para dentro.

Por que um mod ou cliente do Minecraft tocaria código nativo?

A maioria do Java nunca precisa de JNI. Um mod o utiliza quando a JVM sozinha não consegue realizar a tarefa, geralmente gráficos, áudio, integração com o sistema operacional ou uma rotina que precisa ser rápida. A biblioteca nativa faz o trabalho pesado e o JNI é a maneira padrão de carregá-la e chamá-la.

Reutilize uma biblioteca C comprovada

Uma base de código nativa e madura já resolve o problema. Reescrevê-la em Java seria um esforço desperdiçado, então o mod se vincula a ela.

Acesse o sistema operacional

Alguns recursos da plataforma não possuem API Java pura. Uma chamada nativa se torna a única via para acessá-los.

Acelera um caminho quente

Uma rotina numérica apertada ou de baixo nível pode rodar mais rápido como código nativo compilado do que como bytecode na JVM.

Hardware e drivers

Renderização, som e acesso a dispositivos frequentemente estão por trás de bibliotecas nativas que a JNI expõe ao lado Java.

Como funciona uma chamada JNI de ponta a ponta?

O fluxo é idêntico em todas as plataformas: declare o método em Java, compile uma função C correspondente em uma biblioteca compartilhada, carregue-a em tempo de execução, permita que a JVM os vincule por nome e, em seguida, chame através da barreira. Os nomes das funções seguem um padrão fixo para que a JVM possa resolvê-los, e um arquivo de cabeçalho gerado especifica a assinatura exata a ser implementada.

EtapaO que acontece
DeclararUm método Java é escrito com a palavra-chave native e deixado vazio no lado Java.
ConstruirUma função C ou C++ é compilada em uma biblioteca compartilhada: .dll no Windows, .so no Linux, .dylib no macOS.
CarregarO Java chama System.loadLibrary para carregar essa biblioteca durante a execução do programa.
VincularA JVM corresponde cada método native à sua função C por meio de uma assinatura ofuscada.
ChamarO Java invoca o método; o controle cruza para o código nativo e retorna com um resultado.

Qual o custo do JNI para você?

JNI é poderoso e possui arestas afiadas. Como o código nativo é executado fora da rede de segurança da JVM, uma falha ali derruba todo o processo em vez de lançar uma exceção capturável. A memória alocada pelo lado nativo é invisível para o coletor de lixo, então vazamentos se acumulam a menos que sejam liberados manualmente. Cada travessia acarreta uma sobrecarga, o que torna a chamada através da fronteira dentro de um loop apertado cara. E as compilações nativas são travadas na plataforma: um .dll do Windows não será carregado no Linux sem uma compilação separada.

O que compra

  • Acesso direto a bibliotecas C e C++ existentes
  • Um caminho para recursos do sistema operacional e do hardware que a JVM não alcança
  • Execução em velocidade nativa para as rotinas mais importantes

O que custa

  • Uma falha nativa pode derrubar toda a JVM
  • Gerenciamento manual de memória sem um sistema de coleta de lixo de apoio
  • Builds específicos para cada plataforma para manter e distribuir
  • Sobrecarga que cruza fronteiras em loops quentes

JNI vs. a API de Funções Estrangeiras e Memória

O JNI é o mecanismo original, mas já não é o único. As versões mais recentes do Java incluem a API de Funções Estrangeiras e Memória (FFM), projetada para chamar código nativo com menos código repetitivo e garantias de segurança mais rigorosas. O JNI ainda domina as ferramentas existentes porque está presente em todos os lugares e é amplamente compreendido.

JNIAPI FFM
IdadeOriginal, presente desde os primeiros lançamentos do JavaModerna, adicionada em lançamentos recentes
Código repetitivoCabeçalhos gerados, funções C com nomes ofuscadosHandles de métodos definidos em Java, sem código C intermediário
Segurança da memóriaManual; erros podem corromper a JVMSegmentos limitados com verificações mais fortes
AdoçãoUbíquo em bibliotecas existentesCrescente, em novas bases de código

Perguntas Frequentes

Obtenha o Terminus

Construído por pessoas que realmente leem os detalhes internos da JVM.