Estou trabalhando em um projeto Java que usa o JNI. O JNI chama uma biblioteca personalizada que eu mesmo escrevi, digamos mylib.dll, e que depende de uma biblioteca de terceiros, libsndfile-1.dll.
Quando executo meu programa, ele trava com
java.lang.UnsatisfiedLinkError: C:\...path...\mylib.dll: Can't find dependent libraries.
Pesquisei neste site (e em outros) e tentei várias soluções:
Corri o dependency walker. O DW deu alguns avisos - que duas bibliotecas exigidas pelo libsndfile, MPR.DLL e SHLWAPI.DLL, tinham "importações não resolvidas" - mas o DW FAQ disse que esses avisos poderiam ser ignorados com segurança.
Corrigi os nomes dos métodos em mylib.dll, conforme sugerido aqui . Os nomes dos métodos foram de alguma forma mutilados pelo compilador, mas adicionei sinalizadores de linker e os nomes dos métodos dll agora correspondem exatamente aos do meu arquivo de cabeçalho jni.
Coloquei todas essas DLLs no mesmo diretório - o mesmo diretório do .jar que as chama - para garantir que estejam no PATH certo.
Sem dados.
Alguém tem ideia do que está acontecendo?
Estou fazendo meu desenvolvimento no Visual Studio 2010 em um MacBook Pro (via Parallels). Estou fazendo meus testes no Windows XP em um laptop toshiba.
Respostas:
Tenho certeza de que o caminho de classe e o caminho de pesquisa da biblioteca compartilhada têm pouco a ver um com o outro. De acordo com The JNI Book (que reconhecidamente é antigo), no Windows, se você não usar a
java.library.path
propriedade do sistema, a DLL precisa estar no diretório de trabalho atual ou em um diretório listado naPATH
variável de ambiente do Windows .Atualizar:
Parece que a Oracle removeu o PDF de seu site. Atualizei o link acima para apontar para uma instância do PDF que vive na Universidade do Texas - Arlington.
Além disso, você também pode ler a versão HTML da Oracle da Especificação JNI . Ele está na seção Java 8 do site Java e, portanto, esperamos estar por aí por um tempo.
Atualização 2:
Pelo menos no Java 8 (não verifiquei as versões anteriores), você pode fazer:
para encontrar o caminho de pesquisa da biblioteca compartilhada. Procure o valor da
java.library.path
propriedade nessa saída.fonte
CLASSPATH
não é usado de todo. Eu também não tenho certeza se ocwd
é usado.java.library.path
ou simplesmentePATH
funcionará. @dB ', o lugar onde você os tem agora está errado .Quero informar este caso interessante, depois de tentar todo o método acima, o erro ainda está aí. O estranho é que funciona em um computador com Windows 7, mas não é no Windows XP. Então eu uso o dependency walker e descobri no Windows XP que não há VC ++ Runtime como meu requisito de dll. Depois de instalar o pacote VC ++ Runtime aqui, ele funciona perfeitamente. O que me perturbou é que ele continua dizendo Não consigo encontrar bibliotecas dependentes, enquanto intuitivamente a dll dependente de JNI está lá, no entanto, finalmente descobri que a dll dependente de JNI requer outra dl dependente. Eu espero que isso ajude.
fonte
Você precisa carregar sua biblioteca JNI.
System.loadLibrary carrega a DLL do caminho JVM (caminho bin JDK).
Se você quiser carregar um arquivo explícito com um caminho, use System.load ()
Veja também: Diferença entre System.load () e System.loadLibrary em Java
fonte
Verifique se o caminho da sua biblioteca está correto ou não. Claro, você pode usar o seguinte código para verificar o caminho do caminho da biblioteca:
System.out.println(System.getProperty("java.library.path"));
Você pode indicar o java.library.path ao iniciar um aplicativo Java:
fonte
Se você carregar uma versão de 32 bits de sua dll com um JRE de 64 bits, poderá ter esse problema. Este foi o meu caso.
fonte
chromedriver.exe
, mas o driver Selenium para o Chrome, que até onde eu posso dizer só vem na versão de 32 bits.Teve problema idêntico com a máquina XP ao instalar
javacv
eopencv
em combinação com o Eclipse. Descobri que estavam faltando os seguintes arquivos:Depois de instalados, o projeto foi compilado e executado corretamente.
fonte
fonte
Eu encontrei um ótimo artigo escrito por alguns amigos da Keepafe que passou pela mesma coisa que eu. Funcionou para mim, então espero que ajude você também! Leia se estiver interessado ( Os perigos de carregar bibliotecas nativas no Android ) ou apenas use
compile 'com.getkeepsafe.relinker:relinker:1.2.3'
e substituir
System.loadLibrary("myLibrary");
com
ReLinker.loadLibrary(context, "mylibrary");
fonte
Eu costumava ter exatamente o mesmo problema e finalmente foi resolvido.
Coloquei todas as DLLs dependentes na mesma pasta em que mylib.dll foi armazenado e certifique-se de que o compilador JAVA possa encontrá-lo (se não houver mylib.dll no caminho de compilação, haverá um erro relatando isso durante a compilação). O importante que você precisa observar é que você deve se certificar de que todas as libs dependentes são da mesma versão de mylib.dll, por exemplo, se seu mylib.dll for uma versão de lançamento, você também deve colocar a versão de lançamento de todas as suas bibliotecas dependentes lá .
Espero que isso possa ajudar outras pessoas que tenham encontrado o mesmo problema.
fonte
Eu tive o mesmo problema e tentei tudo o que está postado aqui para corrigi-lo, mas nada funcionou para mim. No meu caso, estou usando o Cygwin para compilar a dll. Parece que a JVM tenta encontrar as DLLs JRE no caminho virtual do Cygwin. Eu adicionei o caminho do diretório virtual do Cygwin às DLLs do JRE e agora funciona. Eu fiz algo como:
fonte
Na minha situação, eu estava tentando executar um serviço da web em java no Tomcat 7 por meio de um conector no Eclipse. O aplicativo funcionou bem quando implantei o arquivo war em uma instância do Tomcat 7 em meu laptop. O aplicativo requer um driver jdbc tipo 2 para "IBM DB2 9.5". Por alguma razão estranha, o conector no Eclispe não pôde ver ou usar os caminhos nas variáveis de ambiente do IBM DB2 para alcançar os arquivos dll instalados em meu laptop como o cliente jcc. A mensagem de erro afirmou que não conseguiu encontrar o arquivo dll db2jcct2 ou não conseguiu encontrar as bibliotecas dependentes para esse arquivo dll. Por fim, excluí o conector e o reconstruí. Então funcionou corretamente. Estou adicionando essa solução aqui como documentação, porque não consegui encontrar essa solução específica em nenhum outro lugar.
fonte
Criar uma biblioteca estática funcionou para mim, compilando usando
g++ -static
. Ele empacota as bibliotecas dependentes junto com a construção.fonte
instalar o Microsoft Visual C ++ 2010 SP1 Redistributable Corrigido
fonte
coloque as dlls necessárias na pasta e defina o caminho da pasta na variável de ambiente PATH. certifique-se de que a variável PATH de ambiente atualizada seja refletida.
fonte
Eu estava enfrentando o mesmo problema com a biblioteca ffmpeg depois de fundir dois projetos Android como um projeto.
Na verdade, o problema estava chegando devido a duas versões diferentes da biblioteca ffmpeg, mas elas foram carregadas com os mesmos nomes na memória. Uma biblioteca foi colocada no JNiLibs enquanto a outra estava dentro de outra biblioteca usada como módulo. Não fui capaz de modificar o código do módulo, pois era somente leitura, então renomei o usado em meu próprio código para ffmpegCamera e carreguei-o na memória com o mesmo nome.
System.loadLibrary("ffmpegCamera");
Isso resolveu o problema e agora as duas versões das bibliotecas estão carregando bem como nome e id de processo separados na memória.
fonte
Ao chamar
System.loadLibrary()
, o JVM irá olhar nojava.library.path
sua biblioteca nativa. No entanto, se essa biblioteca nativa declarar quaisquer dependências em outras bibliotecas nativas, o sistema operacional terá a tarefa de localizar essas dependências da biblioteca nativa.Como o sistema operacional não tem o conceito de
java.library.path
, ele não verá nenhum diretório que você colocar no java.library.path. Em vez disso, ele pesquisará apenas os diretórios na variável de ambiente PATH do sistema operacional. Isso é totalmente adequado se a dependência da biblioteca nativa for uma biblioteca nativa do sistema operacional, pois ela será encontrada no PATH. No entanto, se a dependência da biblioteca nativa for uma biblioteca nativa que você ou outra pessoa criou, ela não será encontrada no PATH a menos que você a coloque lá. Este comportamento é estranho, inesperado e não bem documentado, mas está documentado no rastreador de problemas do OpenJDK aqui . Você também pode encontrar outra resposta StackOverflow reforçando essa explicação aqui .Portanto, você tem algumas opções. Você pode carregar cada biblioteca nativa na ordem de dependência correta usando
System.loadLibrary()
ou pode modificar o PATH para incluir os diretórios onde suas bibliotecas nativas estão armazenadas.fonte
Visual C++ Redistributable for VS2012
VSU_4\vcredist_x64.exe
ouVSU_4\vcredist_x84.exe
dependendo da configuração do seu sistemadll
arquivos dentro dalib
pasta, junto com suas outras bibliotecas (por exemplo\lib\win32-x86\your dll files
).fonte