Spring 在 Linux 启动时使用 JNA 加载 .so 文件时出现问题

Issues loading .so file with JNA in Spring Boot on Linux

我有一个用 Java 编写的带有 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,但是在尝试查找文件 [ 时立即失败了=33=] 与前一个文件位于同一目录中。

我应该提一下,在 Windows 上,这工作得很好。 JNA在"jna.library.path".

指定的目录中找到对应的dll文件

windows 行为是在 .dll 所在的目录中搜索依赖库,因此当 jna 将库加载到内存中时,依赖库也会从那里加载。

如果您启动终端 window 并 cd 到 .so 所在的目录,然后 运行 命令:

ldd ./libGTransTF.so

并且提示找不到库libCoreGTrans.so那么可以看到搜索顺序找不到这个位置

运行-time link-loader (ld.so) 使用一组决定在哪里可以找到库。默认行为不包括找到库的目录。

您可以在构建时向库添加一个选项,以在特定位置搜索以查找库。当你构建库时,你可以说在 运行 时间 中搜索 .so 来自 的目录,方法是添加以下行:

-Wl,-rpath,'$ORIGIN'

到 link 行。它需要用常量值 $ORIGIN 填充,否则这不起作用,因此在 makefile 中正确处理可能有点棘手。这是一个在 运行 时得到解决的值。

如果您自己构建库,这一切都很好,但是如果您从其他地方获取库,或者您已经构建了它们并且不想重建它们,您可以使用 patchelf 等工具编辑 .so 的搜索路径以添加其原始位置:

patchelf --set-rpath '$ORIGIN' libGTransTF.so

那么当你 运行:

ldd ./libGTransTF.so

应该可以成功找到libCoreGTrans.so