如何使用Maven将JNI绑定/C库(so/dylib/dll)与Java库一同部署
解决方案:将JNI包装器与多平台C二进制文件一同发布到Maven
针对你的需求,这里提供两种实用方案,适配不同场景:
方案一:把所有平台二进制打包进主JAR(适合小体积二进制)
这种方式让用户只需要引入一个依赖,就能自动适配当前系统加载对应C库。
- 配置Maven资源插件,打包二进制文件
在pom.xml中添加资源配置,将lib目录下的所有平台二进制复制到JAR的META-INF/natives目录:
<build> <resources> <resource> <directory>lib</directory> <targetPath>META-INF/natives</targetPath> <includes> <include>**/*.so</include> <include>**/*.dll</include> <include>**/*.dylib</include> <!-- macOS平台需添加 --> </includes> </resource> </resources> </build>
- 在Java包装器中添加自动加载逻辑
写一段静态代码块,根据当前系统提取对应二进制到临时目录并加载:
public class SdkLoader { static { try { String os = System.getProperty("os.name").toLowerCase(); String arch = System.getProperty("os.arch").toLowerCase(); String nativePath; if (os.contains("linux")) { nativePath = "META-INF/natives/linux-x64/libSdk.so"; } else if (os.contains("win")) { nativePath = "META-INF/natives/win-x64/Sdk.dll"; } else if (os.contains("mac")) { nativePath = "META-INF/natives/osx-x64/libSdk.dylib"; } else { throw new UnsupportedOperationException("不支持当前操作系统:" + os); } // 提取二进制到临时文件(JVM退出时自动删除) InputStream is = SdkLoader.class.getResourceAsStream("/" + nativePath); File tempFile = File.createTempFile("Sdk", nativePath.substring(nativePath.lastIndexOf('.'))); tempFile.deleteOnExit(); try (OutputStream osOut = new FileOutputStream(tempFile)) { byte[] buffer = new byte[1024]; int read; while ((read = is.read(buffer)) != -1) { osOut.write(buffer, 0, read); } } System.load(tempFile.getAbsolutePath()); } catch (Exception e) { throw new RuntimeException("加载本地库失败", e); } } }
- 构建发布
直接执行mvn clean deploy,主JAR会包含所有平台的二进制文件,用户引入依赖后即可自动加载对应库。
方案二:发布带平台分类器的附属JAR(推荐,符合Maven规范)
这种方式主JAR只包含Java代码,各平台二进制打包成独立的带分类器JAR,Maven会自动根据用户系统下载对应版本。
- 编写Assembly配置文件
在项目根目录创建assembly文件夹,为每个平台编写配置文件,比如assembly/linux-x64.xml:
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd"> <id>linux-x64</id> <formats> <format>jar</format> </formats> <fileSets> <fileSet> <directory>lib/linux-x64</directory> <outputDirectory>/</outputDirectory> <includes> <include>libSdk.so</include> </includes> </fileSet> </fileSets> </assembly>
同理创建win-x64.xml、osx-x64.xml等其他平台的配置文件。
- 配置Maven Assembly插件生成分类器JAR
在pom.xml中添加插件配置:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <id>linux-x64</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <descriptor>assembly/linux-x64.xml</descriptor> <classifier>linux-x64</classifier> </configuration> </execution> <execution> <id>win-x64</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <descriptor>assembly/win-x64.xml</descriptor> <classifier>win-x64</classifier> </configuration> </execution> <!-- 其他平台的execution配置 --> </executions> </plugin> </plugins> </build>
- 配置依赖自动匹配
在pom.xml的<dependencies>中添加自身依赖,让Maven根据系统自动选择对应分类器的JAR:
<dependencies> <!-- 主Java包装器依赖 --> <dependency> <groupId>你的groupId</groupId> <artifactId>你的artifactId</artifactId> <version>${project.version}</version> </dependency> <!-- Linux x64 二进制依赖 --> <dependency> <groupId>你的groupId</groupId> <artifactId>你的artifactId</artifactId> <version>${project.version}</version> <classifier>linux-x64</classifier> <scope>runtime</scope> <activation> <os> <name>linux</name> <arch>amd64</arch> </os> </activation> </dependency> <!-- Windows x64 二进制依赖 --> <dependency> <groupId>你的groupId</groupId> <artifactId>你的artifactId</artifactId> <version>${project.version}</version> <classifier>win-x64</classifier> <scope>runtime</scope> <activation> <os> <name>windows</name> <arch>amd64</arch> </os> </activation> </dependency> <!-- 其他平台依赖配置 --> </dependencies>
- 发布所有JAR
执行mvn clean deploy,主JAR和所有带分类器的平台二进制JAR会被发布到Maven仓库。用户只需引入主依赖,Maven会自动下载对应平台的二进制文件。
额外注意事项
- CI流水线集成:在Maven构建前,从C语言流水线拉取最新二进制文件到项目
lib目录,比如通过内部制品库拉取、git子模块同步等方式。 - 签名校验:如果仓库要求签名,确保所有发布的JAR都完成签名。
- 平台扩展:新增平台时,只需添加对应二进制文件和Maven配置即可。
内容的提问来源于stack exchange,提问作者ultimate
相关产品推荐
相关产品推荐

