java - 在 Linux 上的 Spring Boot 中使用 JNA 加载 .so 文件时出现问题

标签 java linux spring-boot jna

我有一个使用 Spring Boot 用 Ja​​va 编写的应用程序。该应用程序需要加载与项目捆绑在一起的 .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文件。

最佳答案

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库。

关于java - 在 Linux 上的 Spring Boot 中使用 JNA 加载 .so 文件时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55847649/

相关文章:

java - 相当于 Java 中的 'where' fortran 关键字吗?

c - 在 Debian 上运行 C 程序的问题

spring-boot - 在 API 网关级别与在单个微服务级别解码 OAuth2 JWT

java - Spring Security 默认登录表单无法加载 CSS 文件(ERR_CONNECTION_TIMED_OUT)

java - Docker 化 Spring Boot 应用程序

java - 使用 JPA 的事务边界和 DTO 转换

linux - 编译时 Ubuntu 14.04 中的 Oracle Developer Studio : Cannot find sys/cdefs. h

linux - Linux 上的 UNC 路径构建

java - 如何在 spring boot 中获得可重现的 Pbkdf2PasswordEncoder 输出?

java - spring SQL Injection中的@Query注解安全吗?