WebSphere应用服务器运行自定义JNI代码时出现UnsatisfiedLinkError
问题描述
Java Web应用包含自定义JNI代码,在WebSphere Application Server中调用时抛出以下错误:
E com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0014E: Uncaught service() exception root cause spring: org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.UnsatisfiedLinkError
但通过命令行运行测试Java程序时,该JNI库可正常工作,测试代码如下:
Test_JNI.java
public class Test_JNI { public static native int vsttestjni(); static { System.load("fullpath/libvsttestjni.so"); } public static void main(String[] args) { int ret = vsttestjni(); System.out.println("Value of ret is :- " + ret); } }
Test_JNI.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class Test_JNI */ #ifndef _Included_Test_JNI #define _Included_Test_JNI #ifdef __cplusplus extern "C" { #endif /* * Class: Test_JNI * Method: vsttestjni * Signature: ()I */ JNIEXPORT jint JNICALL Java_Test_1JNI_vsttestjni (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
vsttestjni.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <jni.h> #include <stdio.h> #include "Test_JNI.h" JNIEXPORT jint JNICALL Java_Test_1JNI_vsttestjni (JNIEnv *env, jclass obj) { return 112; }
问题原因及解决方案
1. 进程权限不足
WebSphere运行用户(如wasadmin)可能没有JNI库文件及父目录的读取权限。命令行测试时使用的是当前用户,权限足够,但WebSphere进程用户权限受限。
- 执行
chmod 755 fullpath/libvsttestjni.so赋予库文件可读可执行权限 - 确保库文件所在的所有父目录对WebSphere用户有读取权限
2. 硬编码路径的问题
直接使用System.load("fullpath/libvsttestjni.so")硬编码路径,可能因WebSphere的环境隔离或路径解析规则导致加载失败。建议改用System.loadLibrary并配置库路径:
- 修改Test_JNI的静态代码块:
static { System.loadLibrary("vsttestjni"); } - 将
libvsttestjni.so放入以下任一目录:- WebSphere全局native库目录:
<WAS_HOME>/lib/native/<操作系统架构> - 应用的
WEB-INF/lib/native目录(需确保WebSphere能识别此路径) - 在WebSphere控制台配置JVM参数,添加
-Djava.library.path=你的库所在目录
- WebSphere全局native库目录:
3. 类加载器隔离冲突
WebSphere采用分层类加载器机制,如果JNI类被父类加载器加载,而本地库仅在应用类加载器可见范围内,会导致链接错误。
- 将JNI类
Test_JNI打包到Web应用的WEB-INF/classes或WEB-INF/lib中,确保由应用类加载器加载 - 若需全局使用,可将JNI类放入WebSphere的共享库,并配置应用依赖该共享库
4. 依赖库缺失
JNI库可能依赖其他系统库,命令行环境中这些依赖库在LD_LIBRARY_PATH中,但WebSphere启动时未包含该路径。
- 用
ldd libvsttestjni.so检查依赖库,例如:ldd libvsttestjni.so - 将缺失的依赖库放入系统标准库目录(如
/usr/lib64),或在WebSphere启动脚本中添加:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/依赖库所在目录
5. 32/64位架构不匹配
WebSphere的JVM位数与JNI库编译位数不兼容,例如64位JVM加载32位库。
- 检查JVM位数:执行
$WAS_HOME/bin/java -version,输出中会标注64-Bit或32-Bit - 检查库位数:执行
file libvsttestjni.so,根据输出确认架构,重新编译对应位数的JNI库
6. Java安全策略限制
WebSphere的Java安全策略可能禁止加载本地库。
- 编辑WebSphere配置文件:
<WAS_HOME>/profiles/<你的Profile>/properties/java.policy - 添加以下权限配置:
permission java.lang.RuntimePermission "loadLibrary.vsttestjni";
内容的提问来源于stack exchange,提问作者Manan Dave

