Problema ao carregar biblioteca com JNI  XML
Índice dos Fóruns » Java Avançado
Autor Mensagem
fcmartins
Java Ninja
[Avatar]

Membro desde: 12/01/2005 09:40:43
Mensagens: 293
Localização: Bragança Paulista- SP
Offline

Estou enfrentando um problema ao carregar a DLL da minha biblioteca JNI.

Eu fiz uma biblioteca, para aprendizado, que permite ao meu programa Java chamar várias funções através da Win32 API, como: MAC address, tamanho do espaço livre em disco, serial do HD, nome da placa de rede, etc.

Coloco a minha DLL na pasta Windows\System32 e tudo funciona perfeitamente. Porém eu observei que vários projetos colocam as DLLs na mesma pasta do JAR que as chama, como por exemplo o SWT e o Systray.

Como eu pretendo distribuir essa biblioteca, eu queria manter a complexidade no mínimo possível, sem mexer em pastas do Sistema Operacional, deixando a DLL na mesma pasta do meu JAR, mas sem usar a diretiva -D do java.exe.

Olhando o código dessas bibliotecas eu vi que eles carregam as DLLs com o comando:

que requer que a DLL esteja em:

Eu já olhei em todo canto, mas não consegui entender como nessas biblioteca eles fizeram para colocar as DLLs na mesma pasta do JAR. Quando eu tento fazer o mesmo eu obtenho a seguinte exceção:

Alguém já passou pelo mesmo problema? Agradeço qualquer ajuda, porque já estou ficando louco, estou a ponto de apagar tudo e esquecer esse negócio de JNI.

Almanaque

{SCJP 1.4}
{SCWCD 1.4}
FLC
JavaGuru

Membro desde: 15/08/2002 15:30:08
Mensagens: 212
Localização: São Paulo
Offline

jah tentou utilizar o System.setProperty?



fcmartins
Java Ninja
[Avatar]

Membro desde: 12/01/2005 09:40:43
Mensagens: 293
Localização: Bragança Paulista- SP
Offline

FLC wrote:jah tentou utilizar o System.setProperty?


Não funciona. É possível mudar o valor da propriedade, mas a JVM não recarrega os valores.

Almanaque

{SCJP 1.4}
{SCWCD 1.4}
fcmartins
Java Ninja
[Avatar]

Membro desde: 12/01/2005 09:40:43
Mensagens: 293
Localização: Bragança Paulista- SP
Offline

Dei uma olhada mais a fundo no SWT e vi que p/ rodar é preciso passar o -D, vou usar assim mesmo.

Almanaque

{SCJP 1.4}
{SCWCD 1.4}
FLC
JavaGuru

Membro desde: 15/08/2002 15:30:08
Mensagens: 212
Localização: São Paulo
Offline

fcmartins wrote:
Não funciona. É possível mudar o valor da propriedade, mas a JVM não recarrega os valores.


hummm.. q coisa... achava que chamando o loadLibrary depois de dar um setProperty pegava-se a propriedade atual. Bom saber disso.
fcmartins
Java Ninja
[Avatar]

Membro desde: 12/01/2005 09:40:43
Mensagens: 293
Localização: Bragança Paulista- SP
Offline

FLC wrote:hummm.. q coisa... achava que chamando o loadLibrary depois de dar um setProperty pegava-se a propriedade atual. Bom saber disso.

Eu nem cheguei a testar, mas quando eu estava pesquisando como resolver meu problema tinha um monte de gente que tinha tentado isso e não tinha conseguido. O que pode ser feito é pegar o diretório atual do JAR (não tenho idéia de como fazer programaticamente) e carregar a DLL com System.load, passando o nome completo do arquivo.

This message was edited 2 times. Last update was at 20/03/2005 21:56:05


Almanaque

{SCJP 1.4}
{SCWCD 1.4}
Dharis
JavaBaby
[Avatar]

Membro desde: 12/11/2003 16:06:56
Mensagens: 99
Localização: Rio Branco, Acre
Offline

fcmartins wrote:Olhando o código dessas bibliotecas eu vi que eles carregam as DLLs com o comando:

que requer que a DLL esteja em:


java.library.path é atualizado pela variável PATH do sistema. Você poderia atualizar a variável PATH do SO.
Normalmente java.library.path inclui o diretório atual ".", então daria pra usar a .dll no mesmo diretório do jar.
* Editado: se você usar -Djava.library.path ele vai reescrever a propriedade e usar apenas o que você indicou.

This message was edited 1 time. Last update was at 21/03/2005 14:43:27


Dharis
Dharis
JavaBaby
[Avatar]

Membro desde: 12/11/2003 16:06:56
Mensagens: 99
Localização: Rio Branco, Acre
Offline

Outra alternativa é usar:

Dharis
fcmartins
Java Ninja
[Avatar]

Membro desde: 12/01/2005 09:40:43
Mensagens: 293
Localização: Bragança Paulista- SP
Offline

Normalmente java.library.path inclui o diretório atual ".", então daria pra usar a .dll no mesmo diretório do jar
O . referencia o local de onde você rodou o java. Se eu rodar um .jar executável funciona, mas não em outros casos.

Só que aí você está assumindo que o jar está no diretório .lib, nem sempre é/será o caso.

O problema, a meu ver, é que o funcionamento da carga das bibliotecas com JNI é muito mal-feito. No google existem várias pessoas que passam pelos memos problemas que eu, é gente que usa SWT e pena p/ distribuir a aplicação com o WebStart, é gente que faz toda sorte de gambiarras p/ poder empacotar uma dll dentro de um .jar, é gente com problema de Dll hell, etc.

Se a JVM carregasse as bibliotecas da mesma forma que os .jars, através do CLASSPATH e permitisse empacotar as bibliotecas dentro de um .jar e acessá-las como um resource todos os problemas estariam resolvidos.

É ridículo esperar que um programador ou usuário do Java fique mexendo em Windows/System32 (ou o equivalente do Linux) ou na pasta de instalação da JDK, sem falar dos Web-containers. Java foi feito p/ ser simples, se eu crio uma biblioteca JNI, o usuário tem que copiar e colar e sair usando.

De toda forma, tem o fórum do Mustang no Java.net, e eu dei minha opinião lá, nos posts abertos que discutem esses problemas, quem puder dê um pitaco também, quem sabe não ajuda:
Make JNI simpler to use
Invoke JNI DLL if packed in same JAR

Almanaque

{SCJP 1.4}
{SCWCD 1.4}
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

O que já verifiquei na prática é:
- DLLs JNI precisam de um instalador, que as ponha no local correto (que ainda acho que é no C:\Windows\System32 - podem me xingar à vontade...) - não dá problema de path ou de não ser encontrada na sua instalação do JDK ou JRE, ou mesmo se você está usando Microsoft JVM, que suporta JNI também.
- Quando você usa DLLs JNI deve-se preparar para problemas. Deve-se reduzir ao máximo a funcionalidade que elas executam diretamente. Por exemplo, nunca usaria uma DLL JNI para criptografia (que pode ser perfeitamente feita em Java, sem problemas); no máximo, para aquelas coisas que realmente não dá para fazer em Java, como chamar algum ActiveX que você realmente precisa chamar para fazer seu sistema funcionar.) Além disso, não se deve chamar DLLs JNI dentro de um servidor de aplicações ou de um 'web container'; deve-se deixar as chamadas segregadas em uma aplicação Java separada (com a qual comunica-se via Sockets ou RMI), para que os problemas em código nativo só "detonem" essa aplicação, não o servidor completo.


[WWW]
 
Índice dos Fóruns » Java Avançado
Ir para:   
Powered by JForum 2.1.8 © JForum Team