Desenvolvimento - Java
JNI: interação Java e outras linguagens
Neste artigo vamos ver conceitos, vantagens e desvantagens da utilização do JNI (Java Native interface) na integração de códigos Java e demais linguagens (no caso Delphi).
por Gustavo S. SemaanO JNI é uma interface de comunicação (API) desenvolvida pela Sun que permitem aos códigos executados pela VM (Java Virtual Machine) interoperarem de forma bidirecional com aplicações e bibliotecas desenvolvidas de outras linguagens, como C/C++, assembly ou Delphi.
Neste artigo iremos conceituar o JNI bem como as vantagens e desvantagens em sua utilização. Abordaremos um exemplo com interação com um código Java acessando uma biblioteca Delphi/Kylix. Não exemplificaremos a contra-partida (Delphi acessando Java) pois nos exigiria mais conhecimentos de Delphi e este não é o foco deste artigo.
Ferramentas utilizadas
- Borland Delphi 7
- Compilador: J2SE SDK
- Ferramenta para geração do DPR
http://home.pacifier.com/~mmead/jni/delphi/files/jni_pas.zip
http://home.pacifier.com/~mmead/jni/delphi/JEDI/PAS/JNI_MD.INC
Conceitos do JNI
Quando desenvolvemos aplicações utilizando Java podemos nos deparar com situações onde esta linguagem pode não atender ou não ser a solução ótima para o dado problema. Problemas relativamente simples como, por exemplo, acesso a uma biblioteca de hardware desenvolvida em C++ ou problemas de performance.
O JNI tem como principal objetivo e qualidade "driblar" as restrições impostas pelo uso da VM. Com ele podemos acessar de classes do Java a bibliotecas desenvolvidas em linguagens com maior suporte a hardware (baixo nível) ou desenvolver em C/C++ algoritmos críticos onde o desempenho é primordial.
Inicialmente o JNI só possuía uma ferramenta que atendia somente C/C++, porém estudiosos interessados nesta solução disponibilizam outras ferramentas para facilitar a comunicação com outras linguagens, como Delphi.
Utilizando JNI você poderá, por exemplo:
- Trabalhar com objetos Java, incluindo arrays
- Chamar métodos Java
- Gerar ou tratar exceções
- Carregar e obter informações das classes
Representação das camadas de comunicação.
Porém existem desvantagens em sua implementação, como:
- Poucas ferramentas para facilitar a criação das interfaces de comunicação.
- O código nativo irá suportar somente a(s) plataforma(as) suportada(s) pela sua linguagem, restringindo uma das principais qualidades da VM, ser multi-plataforma.
Exemplo: Acesso do Java a uma biblioteca desenvolvida em Delphi
Iremos neste exemplo acessar pelo Java uma biblioteca (dll) desenvolvida em Delphi. Como o objetivo do artigo não é focar no desenvolvimento de dlls em Delphi, abordaremos o assunto necessário para bom entendimento do mesmo no quadro Off Topic a seguir.
Passo 1: Desenvolver o código Java.
Criar um arquivo Sysinfo.java com o código
public class SysInfo { //Declaro como nativo e estático este método public native void SysMsg(); static{ //Carrego a dll que já está em um formato entendido pela VM System.loadLibrary("SysLib"); } }
Criar um arquivo JavaExecDelphi.java com o código
/* Irei acessar a classe SysInfo, que tem acesso a DLL desenvolvida em Delphi. Poderia ser um .so desenvolvido no Kylix. */ public class JavaExecDelphi { public static void main(String[] args){ //Instancio a classe que irá acessar a biblioteca SysInfo si = new SysInfo(); //Chamo o metodo que carrega e executa a dll si.SysMsg(); } }
Vamos compilar estes arquivos.
javac Sysinfo.java javac JavaExecDelphi.java
Passo 2: Desenvolver o código Delphi/Kylix.
Para o funcionamento correto da interação são necessárias algumas regras de sintaxe (Link da documentação disponível nas referências deste artigo).
Para facilitar a aplicação destas regras que podem até mesmo causar erros existem ferramentas disponíveis. No próprio pacote JDK possui o javah.exe que gera o código com a sintaxe disponível para C/C++. Como este artigo tem seu foco na interação com Delphi utilizaremos uma ferramenta desenvolvida por Matthew Mead que faz o mesmo para a linguagem Delphi / Kylix (Link da ferramenta disponível na introdução deste artigo).
Descompacte o arquivo jni_pas.zip no mesmo diretório onde salvou o arquivo JNI_MD.INC. Compilemos então o arquivo JavaToDPR.Java e em seguida o executamos para geração do arquivo dpr (Arquivo de projeto do Delphi).
javac JavaToDPR.Java java JavaToDPR SysInfo> SysLib.dpr Arquivo Gerado: SysLib.dpr
O código em vermelho e itálico é o exemplo e não foi gerado pelo JavaToDPR.
Serão utilizados comandos simples para ilustrar o exemplo apenas.
library SysInfo; uses //SysUtils contém informações sobre Data e Hora utilizadas JNI, SysUtils; procedure Java_SysInfo_SysMsg(PEnv: PJNIEnv; Obj: JObject); {$IFDEF WIN32} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF} begin Writeln("===================================================================="); Writeln("Informações do Systema"); Writeln("Data: " + DateToStr(Date)); Writeln("Hora: " + TimeToStr(Time)); Writeln("===================================================================="); end; exports Java_SysInfo_SysMsg; end.
Compilando pelo delphi teremos SysLib.dll.
Passo 3: Executar o JavaExecDelphi
java JavaExecDelphi
Pronto! O resultado de sua biblioteca desenvolvida em Delphi será exibido!
Off Topic
Alguns detalhes para a geração da dll.
É necessário copiar o arquivo borlndmm.dll para o mesmo diretório da gerada (Arquivo existente em qualquer máquina que possua o Delphi instalado).
As dlls deverão estar em algum PATH padrão, por exemplo, System32 dentro do diretório do seu Windows.
Representação das etapas C/C++ e Delphi
Conclusões
Com a utilização do JNI podemos otimizar algoritmos críticos e "driblar" restrições impostas pela VM. Contudo nossa aplicação ficará dependente das plataformas que a linguagem utilizada pode ser executada. Por exemplo, conseguiríamos executar nosso teste apenas em Microsoft Windows ou em alguns Linux que suportem softwares compilados em Kylix.
Referências
ECKEL B. - Thinking in Java, Prenticel Hall, 2a Edição, 2000.
DEITEL, H. M.; DEITEL, P.J. Java- Como Programar, Bookman, 4a. Edição, 2003.
Documentação da Sun relativa ao JNI
Documentação da ferramenta utilizada.