Login Registre-se

Você pode ganhar um iPad 2 na promoção do Javafree

O Portal javafree.org inicia mais uma promoção para os usuários do fórum. Quem publicar mais posts válidos (perguntas ou respostas) entre 16/4 a 13/7 levará para casa um iPad 2 de 16GB!

Clique aqui e saiba mais.
Home > Artigos > Java em Geral >

JNI - Java Native Interface

Publicado por cleuber_s em 23/06/2010 - 122.554 visualizações


comentários: 23

Java Native Interface


Leia também:
JNI - Iteração Java e Delphi
JNI em Linux com GCC


Devido aos vários questionamentos, de várias pessoas, e aqui mesmo no Fórum JavaFree, e por se tratar de um recurso valioso que pode ter uma grande aplicabilidade. Estou disponibilizado este singelo tutorial sobre JNI ( Java Native Interface). Ao longo deste tutorial poderemos formar uma base de conhecimento sobre o assunto, a ser complementado com os livros e tutoriais na web que indico no final do mesmo.

Quote:
Breve respostas:
* O que preciso instalar?
Precisa ter instalado o J2SDK, e é claro o compilador para a biblioteca nativa que você irá utilizar.

* O que preciso conhecer?
Precisa saber lidar com conhecimento básico de Java, exceções e OO; além disso conhecer bem a linguagem da biblioteca nativa.

* Existe dificuldade?
Não existe dificuldade desde que preenchido os pré-requisitos anteriores.


1. Visão Geral de JNI

A Java Native Interface, é um framework que fornece recursos, com a Máquina Virtual Java, para utilização de recursos específicos em determinado Sistema Operacional, ou biblioteca compartilhada e vice-versa. Pelo motivo o qual os Sistemas Virtuais não tem acesso direito à funções do hardware e etc. Com a JNI esta barreira é quebrada. É óbvio que a portabilidade do Java desaparecerão, porém recursos como impressoras fiscais, porta COMX, Modem, USB, e etc podem ser facilmente acessados. Estarei dando exemplos no decorrer deste tutorial.

A JNI permite que um código escrito em Java, utilize a implementação de uma biblioteca escrita em C/C++, Assembler, e outras tantas linguagens de programação.

Usa-se JNI em determinadas situações em que um código Java não pode acessar certos recursos, por causa da estrutura dos Sistemas Vituais (sob qual a Máquina Virtual Java foi implementada).

Além disso, você pode ter um conjunto de bibliotecas escritas em outras linguagens, e pode querer disponibilizá-las em seus programas Java. Isso facilita até o reuso de aplicações não-java. Pode ser usado para implementação de pontos críticos, em aplicações que exigam recursos de baixo-nível como código IN LINE, Assembler, e sua aplicação Java pode chamar todas essas funções.

A JNI, também habilita a você o uso das vantagens da Linguagem de Programação Java em seus métodos nativos, você pode capturar e lançar exceções de uma biblioteca qualquer, e tratá-las dentro de seu programa Java.

Para exemplo, a figura seguinte mostra como um programa usando código em C, pode usar JNI para ligação com classes Java.

0

Facilmente podemos ver que o JNI, serve para interagir entre programas Java e outros programas escritos em liguagens diferentes. A figura abaixo demonstra isso, juntamente com a possibilidade do tratamento de exceções e outras implementações da base de uma aplicação escrita em C.

0


[size=18:d0efc1a997]2. Escrevendo um programa Java com métodos nativos.[/size:d0efc1a997]

A partir de agora criaremos um pequeno programa Java(o básico Hello World!), porém escrito em métodos nativos. A seguinte figura ilustra como será a estrutura de nossa aplicação:

0

Vamos implementar uma Classe chamada HelloWorld, e declarar um de seus métodos nativo.

Quote:
*Método nativo é um função que foi chamada diretamente de uma bibloteca, externa à sua aplicação Java.




O método nativo displayHelloWorld(), é o método "carregado" pelo JNI, através do comando System.loadLibrary("hello"). A palavra chave native indica ao compilador que é uma função de uma biblioteca escrita em uma outra linguagem. Existe um segmento de código nesta classe que é estático, determinando que os métodos nativos carregados podem ser usados ao longo da implementação da classe. O argumento passado em System.loadLibrary é o recurso compartilhado que iremos usar, a biblioteca específica que faremos depois.

Quote:
Em seguida compile o código acima.
javac HelloWorld.java


Agora iremos desenvolver a implementação do método nativo, em outra linguagem que não seja Java.
Agora bastante atenção, iremos usar um recurso muito útil que o ambiente da JSDK nos oferece, o utilitário javah. Iremos gerar este código(o HEADER) como arquivo HelloWorld.h, que está ecrito na linguagem C++.

Quote:
Execute o seguinte comando no arquivo com o utilitário do JSDK na sua classe:
javah -jni HelloWorld


A assinatura do método seguinte indica que o método será exportado pelo JNI, e usado na nossa classe HelloWorld.class:



Neste provesso é utilizada a biblioteca jni.h, que vem no jsdk(na pasta includes), esta biblioteca fornece os mecanismos JNI para o método interagir com nossa classe.
Adota-se como nomenclatura o padrão, a linguagem da exportação em seguida o underline, depois o pacote, underline, e o nome do método em si.

0

Agora temos abaixo a implementação do método nativo e o código completo que deve ser salvo como HeloWorldImp.c



Este método imprime o texto "HelloWorld!" com o comando printf.

    - jni.h - Esse arquivo prove infomações que o código nativo precisa para interagir com a JRE.

    - HelloWorld.h - O arquivo h. que você gerou anteriormente.

    - stdio.h - fornece mecanismos de saída (printf) e outros mais.


Além de criar os arquivos iremos também compartilhar as bibliotecas. Lembre-se que na implementação da classe HelloWorld, havia um trecho de código chamado System.loadLibrary("hello"). Então é necessário compilar essas bibliotecas, e torná-las compartilhadas para que a classe possa encontrá-las. Criaremos uma dynamic link library (DLL) chamada hello.dll. Como o processo para criar uma DLL exige a construção de um compilador. Eu estou usando o Microsoft Visual C++ Toolkit 2003 , porém por praticidade estou disponibilizando os arquivos logo abaixo.

Mas para quem for utilizar este mesmo compilador segue a linha de comando para gerar a DLL:


Ob.: Talvez você precisará copiar os aquivos "jni.h" e "jni_md.h" do J2SDK, para o diretório INCLUDE do compilador C++.

O compilador gerará alguns arquivos, mas nós precisaremos apenas do hello.dll. Esse arquivo deve ser posto no diretório de sua aplicação Java.
Depois disso devemos rodar a nossa classe HelloWorld usando o interpretador Java:

Quote:
java HelloWorld


A saída será o seguinte:

Quote:
Hello World!


A implementação de JNI, abre uma grande gama de possibilidades que podem ser aproveitadas, dadas as limitações da JVM. Estarei implementando a seguir um básico aplicativo , que retira os dados de variáveis de um código nativo.
Vimos, no entanto, a utilização desses códigos nativos em um programa Java de forma a executar somente funções pré-definidas. Mas agora aprederemos como implementar uma interação entre Java e uma outra linguagem.


. Interagindo Java e Programas Nativos

A Java Native Interface define um padrão de nomes e convenções de funções que só a Máquina Virtual Java pode localizar e invocar nos métodos nativos. Esta parte do tutorial ensina, como esses padrões podem ser usados para criar funções JNI e como declarar tipos e como eles podem ser corretamente usados tanto pelo programa Java, como pelo método Nativo.

É necessário lembrar que na declaração de um método nativo no Java ele precisa:

    - Ter a palavra-chave native em sua assinatura.

    - Não ter implementação alguma, no corpo do método.


Vamos implementar agora um novo exemplo que pega informações passadas como parâmetros de uma aplicação Java, processa em código nativo e devolve:


Quote:
>>Desta vez temos o método nativo com um tipo de retorno inteiro e um parâmetro.


Compile o código:

Quote:
javac Prompt.java


Vamos gerar o header da biblioteca automaticamente com o comando:

Quote:
javah -jni Prompt


Veja que o arquivo gerado contém o seguinte:



Podemos ver que foi gerado um método nativo que contém um tipo de retorno jint, e parâmetros jint e jobject. Eles são tipos normatizados pela JNI para possibilitar a comunicação entre aplicativos. Isso faz com que o compilador C++ possa mapear todos os tipos usados e os reconheça, de acordo com a biblioteca importada (jni.h).
Abaixo segue uma tabela com os tipos Java e seus equivalentes JNI:

Quote:
Tipo Java | Tipo Nativo | Tam. em bits
--------------------------------------------
boolean | jboolean | 8, sem sinal
byte | jbyte | 8
char | jchar | 16, sem sinal
short | jshort | 16
int | jint | 32
long | jlong | 64
float | jfloat | 32
double | jdouble | 64
void | void | n/a


Desta forma vemos que, com foi dito antes, a JNI é uma interface entre códigos Java e outras linguagens. Tendo a implementação JNI e seguindo seus padrões de tipos, objetos podemos facilmente estabelecer uma comunicação entre recursos de diferentes tecnologias. Como a linguagem C++ é Orientada à Objetos podemos usar recursos entre ambas, e além disso, C++ nos fornece acesso a recursos de baixo nível (low level) que podemos usar em nossas aplicações Java.
Abaixo segue também a implementação de objetos na JNI. Os objetos são passados por referência, a JNI implementa um conjunto de tipos que são todos subclasses (conceitualmente), de jobject como segue:

0

Agora segue a respectiva implementação do método nativo, do arquivo salvo como PromptImp.c, que deve ser compilado gerando a DLL prompt.dll:



Assim você pode compilar este código no seu compilador C++, ou como já foi descrito acima, gerando a DLL prompt.dll e rodando a classe java Prompt.class, teremos o seguinte resultado:

Quote:
java Prompt
Resultado: 4


Podemos ver desta forma, que o JNI pode extender as potencialidades da linguagem Java, dando recursos que o Java pode não ter, poém sendo agregado à uma linguagem como o C++ pode ser bastante poderoso no acesso à recursos que lhe são limitados. A JNI não possibilita a interface com o C++, apenas, mas com DELPHI, e qualquer oura linguagem que tenha uma biblioteca JNI disponível, pois é ela que faz essa interação. Assim podemos acessar desde de espaço em disco e memória, até portas COM[X] para enviar e receber dados quaisquer.

Espero que tenha agregado conhecimento, um abraço!



Leia também:
JNI - Iteração Java e Delphi
JNI em Linux com GCC


comentários: 23