在OSGi应用中使用Google OR-Tools遇UnsatisfiedLinkError问题求助
已完成的配置
- pom.xml依赖配置:
<dependency> <groupId>com.google.ortools</groupId> <artifactId>ortools-java</artifactId> <version>9.11.4210</version> </dependency> <dependency> <groupId>com.google.ortools</groupId> <artifactId>ortools-linux-x86-64</artifactId> <version>9.11.4210</version> </dependency>
- features.xml打包配置:
<bundle>wrap:mvn:com.google.ortools/ortools-java/9.11.4210</bundle> <bundle>wrap:mvn:com.google.ortools/ortools-linux-x86-64/9.11.4210</bundle>
- app.xml构件配置:
<artifact>mvn:com.google.ortools/ortools-java/9.11.4210</artifact> <artifact>mvn:com.google.ortools/ortools-linux-x86-64/9.11.4210</artifact>
- JNI库加载代码:
静态代码块加载jniortools库无报错:
static { try { System.loadLibrary("jniortools"); } catch (UnsatisfiedLinkError exception) { logger.info(exception.getMessage()); } }
报错详情
调用MPSolver solver = MPSolver.createSolver("GLOP");时抛出错误:
java.lang.UnsatisfiedLinkError: 'long com.google.ortools.linearsolver.mainJNI.MPSolver_createSolver(java.lang.String)'
at com.google.ortools.linearsolver.mainJNI.MPSolver_createSolver(Native Method) ~[?:?]
at com.google.ortools.linearsolver.MPSolver.createSolver(MPSolver.java:140) ~[?:?]
1. 修正wrap命令的Native资源与包导出配置
ortools-linux-x86-64包含JNI本地库,直接wrap无法让OSGi正确识别资源位置。需在features.xml中补充Bundle-NativeCode和Export-Package配置:
<bundle>wrap:mvn:com.google.ortools/ortools-java/9.11.4210$Export-Package=com.google.ortools.*;version=9.11.4210</bundle> <bundle>wrap:mvn:com.google.ortools/ortools-linux-x86-64/9.11.4210$Bundle-NativeCode=lib/*;osname=Linux;processor=x86-64,lib/*;osname=linux;processor=x86_64&Export-Package=com.google.ortools.*;version=9.11.4210</bundle>
Bundle-NativeCode指定本地库路径及适配的系统架构,让OSGi容器能定位并加载JNI库。Export-Package确保ortools-java能访问到本地库对应的JNI类。
2. 改用OSGi原生的本地库加载方式
避免使用System.loadLibrary,改用Bundle.loadLibrary确保从正确的bundle上下文加载本地库,解决类加载器不一致问题:
static { try { Bundle bundle = FrameworkUtil.getBundle(YourApplicationClass.class); if (bundle != null) { bundle.loadLibrary("jniortools"); } else { logger.error("无法获取当前Bundle上下文"); } } catch (UnsatisfiedLinkError | IllegalArgumentException e) { logger.error("JNI库加载失败: {}", e.getMessage()); } }
3. 调整Bundle启动顺序
确保ortools-java和ortools-linux-x86-64先于应用Bundle启动,在features.xml中通过start-level指定:
<bundle start-level="50">wrap:mvn:com.google.ortools/ortools-java/9.11.4210$Export-Package=com.google.ortools.*;version=9.11.4210</bundle> <bundle start-level="50">wrap:mvn:com.google.ortools/ortools-linux-x86-64/9.11.4210$Bundle-NativeCode=lib/*;osname=Linux;processor=x86-64,lib/*;osname=linux;processor=x86_64&Export-Package=com.google.ortools.*;version=9.11.4210</bundle> <!-- 应用Bundle启动级别高于依赖Bundle --> <bundle start-level="60">mvn:your/group/your-app/1.0.0</bundle>
4. 验证本地库提取路径权限
OSGi容器会将Bundle中的本地库提取到临时目录,确保该目录有读写权限,可通过JVM参数指定自定义临时路径:
-Djava.io.tmpdir=/path/to/writable/temporary-folder
同时检查ortools-linux-x86-64 Bundle中是否存在libjniortools.so,且文件权限正常。
内容的提问来源于stack exchange,提问作者Osama Abuhamdan

