M1 Mac OpenJDK17环境JBLAS报UnsatisfiedLinkError如何解决
问题概述
- 运行环境:搭载M1芯片的Mac OSX Monterey系统,使用OpenJDK 17运行Kotlin应用
- 已完成配置:Maven pom.xml中引入JBLAS依赖;通过brew安装lapack、openblas库;将
/opt/homebrew/opt/lapack、/opt/homebrew/opt/openblas加入LD_LIBRARY_PATH;已从App Store安装XCode - 测试现象:编写了两个JUnit测试用例,其中双精度矩阵创建、加法的测试可正常通过,调用求解线性方程
A*x = b的测试抛出UnsatisfiedLinkError失败。
测试代码如下:
package fea import org.jblas.DoubleMatrix import org.jblas.Solve import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test class JBlasTest { @Test fun `create and add two double matricies`() { val n = 3 val a = DoubleMatrix(n, n, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0) val b = DoubleMatrix.ones(n, n).mul(2.0) val expected = DoubleMatrix(n, n, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0) val actual = a.add(b) Assertions.assertEquals(expected, actual) } @Test fun `first solver`() { val n = 3 val a = DoubleMatrix(n, n, 1.0, 1.0, 2.0, 2.0, 4.0, -3.0, 3.0, 6.0, -5.0) val b = DoubleMatrix(n, 1, 9.0, 1.0, 0.0) val expected = DoubleMatrix(n, 1, 1.0, 2.0, 3.0) val actual = Solve.solve(a, b) Assertions.assertEquals(expected, actual) } }
报错信息如下:
java.lang.UnsatisfiedLinkError: 'int org.jblas.NativeBlas.dgesv(int, int, double[], int, int, int[], int, double[], int, int)'
- 已尝试操作:拉取JBLAS源码本地执行
mvn install,构建阶段测试即因链接错误失败,测试报告中存在大量同类链接错误;检索JBLAS源码未找到dgesv方法实现,怀疑需要适配M1架构调整构建配置。
根因说明
dgesv是LAPACK标准库中用于求解线性方程组的核心函数,brew安装的OpenBLAS已经完整包含BLAS和LAPACK的实现,依赖本身没有缺失。- macOS系统不会将
LD_LIBRARY_PATH环境变量传递给GUI启动的程序(比如IntelliJ IDEA),且Java加载原生库默认读取的是java.library.path系统属性,而非LD_LIBRARY_PATH,所以之前的路径配置不生效。 - 官方发布的JBLAS 1.2.19及更早稳定版本没有提供arm64架构(M1系列芯片)的预编译原生动态库。矩阵加法这类纯Java实现的操作不需要调用原生接口,可以正常运行;一旦调用
dgesv这类依赖BLAS/LAPACK原生实现的接口,就会因为找不到对应架构的绑定方法抛出链接错误。 - 如果本地安装的是x86架构的OpenJDK(通过Rosetta 2转译运行),也无法加载arm64架构的原生库,会触发同类错误。
解决步骤
按顺序操作即可:
- 先确认本地JDK架构,终端执行
java -version,如果输出中没有x86_64标识,就是正常的arm64版本,否则需要重装arm64版本的OpenJDK 17。 - 不需要单独配置
LD_LIBRARY_PATH,如果是在IDE中运行测试,在测试的JVM启动参数中添加如下配置,指定OpenBLAS库路径:
-Djava.library.path=/opt/homebrew/opt/openblas/lib
如果是通过Maven命令行跑测试,在pom.xml中给maven-surefire-plugin添加参数配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M7</version> <configuration> <argLine>-Djava.library.path=/opt/homebrew/opt/openblas/lib</argLine> </configuration> </plugin>
- 如果上述配置后仍然报错,就本地编译适配M1架构的JBLAS包,不需要修改Makefile,编译前先在终端设置环境变量指定OpenBLAS路径,再执行构建安装:
export BLAS_PATH=/opt/homebrew/opt/openblas/lib export LAPACK_PATH=/opt/homebrew/opt/openblas/lib mvn clean install
构建完成后,项目引用本地Maven仓库中编译好的JBLAS版本,即可正常调用所有求解、分解类的原生接口。
内容的提问来源于stack exchange,提问作者duffymo
相关产品推荐
相关产品推荐

