Cómo reparar un UnsatisfiedLinkError (No se pueden encontrar bibliotecas dependientes) en un proyecto JNI

Estoy trabajando en un proyecto de Java que usa el JNI. El JNI llama a una biblioteca personalizada que he escrito, digamos mylib.dll, y eso depende de una biblioteca de terceros, libsndfile-1.dll.

Cuando ejecuto mi progtwig, falla con

java.lang.UnsatisfiedLinkError: C:\...path...\mylib.dll: Can't find dependent libraries. 

He buscado en este sitio (y en otros) y he intentado una serie de correcciones:

  1. Ejecuté el walker de dependencias. DW dio un par de advertencias: que las dos bibliotecas requeridas por libsndfile, MPR.DLL y SHLWAPI.DLL tenían “importaciones no resueltas”, pero las preguntas más frecuentes de DW decían que estas advertencias podían ignorarse de forma segura.

  2. Repare los nombres de los métodos en mylib.dll, como se sugiere aquí . Los nombres de los métodos de alguna manera habían sido destrozados por el comstackdor, pero agregué indicadores de enlazadores y los nombres de los métodos dll ahora coinciden exactamente con los del archivo de encabezado jni.

  3. Puse todas estas DLL en el mismo directorio, el mismo que el .jar que las llama, para asegurarme de que están en la RUTA correcta.

No dados.

¿Alguien tiene alguna idea de lo que está pasando?

Estoy haciendo mi desarrollo en Visual Studio 2010 en una MacBook pro (a través de Parallels). Estoy haciendo mis pruebas en Windows XP en una computadora portátil Toshiba.

Estoy bastante seguro de que el classpath y la ruta de búsqueda de la biblioteca compartida tienen poco que ver el uno con el otro. Según The JNI Book (que ciertamente es antiguo), en Windows si no usa la propiedad del sistema java.library.path , la DLL debe estar en el directorio de trabajo actual o en un directorio enumerado en la PATH entorno Windows PATH .


Actualizar:

Parece que Oracle ha eliminado el PDF de su sitio web. He actualizado el enlace de arriba para señalar una instancia del PDF que vive en la Universidad de Texas – Arlington.

Además, también puede leer la versión HTML de Oracle de la especificación JNI . Eso vive en la sección Java 8 del sitio web de Java y, con suerte, estará disponible por un tiempo.


Actualización 2:

Al menos en Java 8 (no he comprobado las versiones anteriores) puedes hacer:

 java -XshowSettings:properties -version 

para encontrar la ruta de búsqueda de la biblioteca compartida. Busque el valor de la propiedad java.library.path en ese resultado.

Quiero informar este interesante caso, después de probar todo el método anterior, el error sigue ahí. Lo extraño es que funciona en una computadora con Windows 7, pero en Windows XP no lo es. Luego uso el cajero de dependencias y encuentro en el Windows XP que no hay VC ++ Runtime como mi requisito dll. Después de instalar el paquete VC ++ Runtime aquí funciona como un encanto. Lo que me molestó es seguir diciendo No se pueden encontrar bibliotecas dependientes, mientras que intuitivamente el dll dependiente de JNI está ahí, sin embargo, finalmente resulta que el dll dependiente de JNI requiere otro dl dependiente. Espero que esto ayude.

Necesitas cargar tu biblioteca JNI.

System.loadLibrary carga el archivo DLL desde la ruta JVM (ruta bin JDK).

Si desea cargar un archivo explícito con una ruta, use System.load ()

Ver también: Diferencia entre System.load () y System.loadLibrary en Java

Verifique que la ruta de su biblioteca sea correcta o no. Por supuesto, puede usar el siguiente código para verificar la ruta de acceso de su biblioteca: System.out.println(System.getProperty("java.library.path"));

Puede asignar java.library.path al iniciar una aplicación Java:

 java -Djava.library.path=path ... 

javacv un problema idéntico con la máquina XP al instalar javacv y opencv en combinación con Eclipse. Resultó que me faltaban los siguientes archivos:

  • msvcp100.dll
  • msvcr100.dll

Una vez que se instalaron, el proyecto compiló y ejecutó OK.

Si carga una versión de 32 bits de su dll con un JRE de 64 bits podría tener este problema. Este era mi caso.

Solía ​​tener exactamente el mismo problema, y ​​finalmente fue resuelto.

Puse todas las DLL dependientes en la misma carpeta donde se almacenó mylib.dll y me aseguro de que el comstackdor JAVA pudiera encontrarla (si no hay mylib.dll en la ruta de comstackción, habría un error al informar esto durante la comstackción). Lo importante que debe observar es que debe asegurarse de que todas las bibliotecas dependientes tengan la misma versión que mylib.dll, por ejemplo, si su mylib.dll es la versión de lanzamiento, entonces también debe colocar allí la versión de lanzamiento de todas sus bibliotecas dependientes. .

Espero que esto pueda ayudar a otros que han encontrado el mismo problema.

Tuve el mismo problema e intenté todo lo que se publicó aquí para solucionarlo, pero ninguno funcionó para mí. En mi caso, estoy usando Cygwin para comstackr el dll. Parece que JVM intenta encontrar las DLL de JRE en la ruta virtual de Cygwin. Agregué la ruta del directorio virtual de Cygwin a las DLL de JRE y funciona ahora. Hice algo como:

SET PATH = “/ cygdrive / c / Archivos de progtwig / Java / jdk1.8.0_45”;% PATH%

En mi situación, estaba tratando de ejecutar un servicio web de Java en Tomcat 7 a través de un conector en Eclipse. La aplicación funcionó bien cuando implementé el archivo de guerra en una instancia de Tomcat 7 en mi computadora portátil. La aplicación requiere un controlador jdbc tipo 2 para “IBM DB2 9.5”. Por alguna extraña razón, el conector en Eclispe no pudo ver ni usar las rutas en las variables de entorno de IBM DB2, para llegar a los archivos dll instalados en mi computadora portátil como el cliente jcc. El mensaje de error indicó que no pudo encontrar el archivo dll db2jcct2 o no pudo encontrar las bibliotecas dependientes para ese archivo dll. Finalmente, eliminé el conector y lo reconstruí. Entonces funcionó correctamente. Estoy agregando esta solución aquí como documentación, porque no pude encontrar esta solución específica en ningún otro lado.

  • Respuesta corta: para el error “no se puede encontrar la biblioteca dependiente”, verifique su $ PATH (corresponde al punto # 3 a continuación)
  • Respuesta larga:
    1. Mundo puro de Java: jvm usa “Classpath” para encontrar archivos de clase
    2. JNI world (java / native limit): jvm usa “java.library.path” (que por defecto es $ PATH) para encontrar dlls
    3. mundo nativo puro: el código nativo usa $ PATH para cargar otras dlls

Encontré un excelente artículo de algunos amigos en keepsafe que pasó por lo mismo que yo hice. Me funcionó, ¡así que espero que también te ayude! Lea si está interesado ( Los peligros de cargar bibliotecas nativas en Android ) o simplemente use

compile 'com.getkeepsafe.relinker:relinker:1.2.3'

y reemplazar

 System.loadLibrary("myLibrary"); 

con

 ReLinker.loadLibrary(context, "mylibrary"); 
  1. Vaya a http://tess4j.sourceforge.net/usage.html y haga clic en Visual C++ Redistributable for VS2012
  2. Descárguelo y ejecute VSU_4\vcredist_x64.exe o VSU_4\vcredist_x84.exe según la configuración de su sistema
  3. Coloque sus archivos dll dentro de la carpeta lib , junto con sus otras bibliotecas (por ejemplo, \lib\win32-x86\your dll files ).