我有一个用Java Boot用Spring Boot编写的应用程序。该应用程序需要加载与该项目捆绑在一起的.so文件,我正在使用JNA来完成。但是,JNA加载程序似乎无法拾取.so文件,因此应用程序无法启动。
我尝试从IntelliJ内运行应用程序,并使用“ java -jar”运行打包的.jar。 .so文件暂时保存在src / main / resources / linux-x86-64中。我尝试将它们保存在其他目录中,例如src / main / resources / libs / linux-x86-64并设置属性“ jna.library.path”,但JNA仍然找不到文件。
这是JNA的调试日志:
Trying (via loadLibrary) jnidispatch
Looking in classpath from sun.misc.Launcher$AppClassLoader@18b4aac2 for /com/sun/jna/linux-x86-64/libjnidispatch.so
Found library resource at jar:file:/home/dalivi/.m2/repository/net/java/dev/jna/jna/4.5.0/jna-4.5.0.jar!/com/sun/jna/linux-x86-64/libjnidispatch.so
Trying /tmp/jna--1339148563/jna4246531844315283838.tmp
Found jnidispatch at /tmp/jna--1339148563/jna4246531844315283838.tmp
Looking for library 'GTransTF'
Adding paths from jna.library.path: null
Trying libGTransTF.so
Adding system paths: [/usr/lib/x86_64-linux-gnu, /lib/x86_64-linux-gnu, /lib64, /usr/lib, /lib, /lib/i386-linux-gnu, /usr/lib/i386-linux-gnu, /usr/lib/x86_64-linux-gnu/libfakeroot]
Trying libGTransTF.so
Looking for version variants
Looking in classpath from sun.misc.Launcher$AppClassLoader@18b4aac2 for GTransTF
Found library resource at file:/home/dalivi/Workspace/java/geotransboot/target/classes/linux-x86-64/libGTransTF.so
Looking in /home/dalivi/Workspace/java/geotransboot/target/classes/linux-x86-64/libGTransTF.so
2019-04-25 12:43:38.032 ERROR 25897 --- [o-auto-1-exec-1] s.l.g.c.TransformationRestController : Handler dispatch failed; nested exception is java.lang.UnsatisfiedLinkError: libCoreGTrans.so: cannot open shared object file: No such file or directory
我似乎确实在目录中找到以下文件之一: libGTransTF.so ,但是当尝试查找存在的文件 libCoreGTrans.so 时,立即失败与上一个文件位于同一目录中。
我应该提到,在Windows上,这很好用。 JNA在“ jna.library.path”指定的目录中找到相应的dll文件。
答案 0 :(得分:4)
Windows的行为是在.dll
所在的目录中搜索依赖库,因此,当jna将库加载到内存中时,依赖库也将从那里加载。
如果启动终端窗口并cd到.so
所在的目录,然后运行命令:
ldd ./libGTransTF.so
,它表明它找不到库libCoreGTrans.so
,然后您会发现搜索顺序找不到该位置。
运行时链接加载器(ld.so
)使用一组有关在哪里找到库的决定。默认行为不包括找到该库的目录。
在构建时可以在库中添加一个选项以在特定位置搜索以查找库。构建库时,您可以说要在目录中搜索.so
来自运行时的目录,方法是添加以下行:
-Wl,-rpath,'$ORIGIN'
到链接行。它需要使用常量值$ORIGIN
进行填充,否则它将无法正常工作,因此在makefile中正确设置可能有些棘手。这是一个在运行时可解决的值。
如果您自己构建库,那么一切都很好,但是如果您要从其他地方获取库,或者您已经构建了库并且不想重建它们,则可以使用patchelf
之类的工具来编辑.so
的搜索路径以添加其原始位置:
patchelf --set-rpath '$ORIGIN' libGTransTF.so
然后在您运行时:
ldd ./libGTransTF.so
它应该能够成功找到libCoreGTrans.so
库。