如何用Maven将*.so文件打包进*.jar并实现加载?部署遇阻求助
解决Linux下Spring Boot Jar加载内部.so文件的问题
问题根源
System.loadLibrary("mylib")依赖系统库路径或java.library.path,Jar内的.so文件不在这些路径范围内,直接调用无法加载。- Jar包属于压缩归档文件,内部资源无法通过
getResource("//")获取文件系统路径,因此会返回null并报错。 - 将.so文件放入
BOOT-INF/lib目录时,Spring Boot会误将其识别为嵌套Jar包尝试解析,触发错误:Exception in thread "main" java.lang.IllegalStateException: 无法获取BOOT-INF/lib/libmylib.so条目对应的嵌套归档文件
正确实现步骤
1. Maven打包配置:将.so文件打包到Jar指定目录
在pom.xml中配置资源插件,把.so文件复制到Jar的BOOT-INF/classes/native自定义目录下,避免与其他资源冲突:
<build> <resources> <resource> <directory>src/main/resources/native</directory> <targetPath>BOOT-INF/classes/native</targetPath> <includes> <include>**/*.so</include> </includes> </resource> </resources> <!-- 保留原有Spring Boot打包插件配置 --> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
将libmylib.so放入项目的src/main/resources/native目录中。
2. 编写加载代码:提取Jar内的.so到临时文件再加载
Jar内的资源无法直接被System.load加载,需先将.so文件复制到系统临时目录,再加载临时文件:
public class NativeLibLoader { public static void loadMylib() throws IOException { // 读取Jar内的.so资源 String libResourcePath = "/native/libmylib.so"; try (InputStream is = NativeLibLoader.class.getResourceAsStream(libResourcePath)) { if (is == null) { throw new RuntimeException("未找到libmylib.so资源"); } // 创建临时文件,JVM退出时自动删除 File tempLibFile = File.createTempFile("libmylib", ".so"); tempLibFile.deleteOnExit(); // 将资源写入临时文件 try (FileOutputStream fos = new FileOutputStream(tempLibFile)) { byte[] buffer = new byte[1024]; int readLen; while ((readLen = is.read(buffer)) != -1) { fos.write(buffer, 0, readLen); } } // 加载临时文件中的本地库 System.load(tempLibFile.getAbsolutePath()); } } }
在业务代码初始化阶段调用NativeLibLoader.loadMylib()即可完成加载。
3. 运行Jar包
保持原有运行命令不变:
java -jar demo.jar -server -Dfile.encoding=UTF-8 -Dspring.profiles.active=prod
额外说明
- 临时文件会在JVM退出时自动删除,不会残留垃圾文件。
- 若需适配多架构(如x86_64、arm64),可根据系统架构动态选择对应路径的.so文件,例如
/native/x86_64/libmylib.so。
内容的提问来源于stack exchange,提问作者豆沙饼
相关产品推荐
相关产品推荐

