记录处理:Caused by: java.lang.UnsatisfiedLinkError
异常截图:
Caused by: java.lang.UnsatisfiedLinkError: /root/.cache/JNA/temp/jna6466124598407234281.tmp: cannot open shared object file: No such file or directory
at com.sun.jna.Native.open(Native Method)
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:277)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:461)
at com.sun.jna.Library$Handler.<init>(Library.java:192)
at com.sun.jna.Native.loadLibrary(Native.java:646)
at com.sun.jna.Native.loadLibrary(Native.java:630)
问题分析:
我这是SpringBoot工程,启动的过程中,需要加载某个jar包,jar包中包含.so文件,当需要使用.so(动态链接库)的时候需要用Native.loadLibrary()去加载.so文件,
这个Native类位于jna.jar中,这个jar包与JDK有对应的匹配关系,建议按照参考去适配
<dependency><groupId>net.java.dev.jna</groupId><artifactId>jna</artifactId><version>5.7.0</version>
</dependency>
一开始怀疑是jna与JDK不匹配导致,或者系统缺少对应的lib库,但是都 一 一 排除,最后发现就是jar包中的.so文件有问题,无法解决
处理过程:
JNA 的 native 库依赖系统底层库(如 glibc
、libstdc++
等),如果系统缺少这些库,会导致加载失败
jna.jar包加载动态库文件可以开启DEBUG日志,可以便于查看加载过程
要开启 JNA(Java Native Access)的 DEBUG 日志,以便调试 native 库加载、函数调用等细节,可以通过配置 Java 日志系统或设置 JNA 特定的系统属性来实现。以下是具体方法:
1. 通过系统属性开启 JNA 调试日志
JNA 内置了调试模式,可通过设置以下系统属性启用,最简单直接:
启动时添加 JVM 参数:
bash
java -Djna.debug_load=true -Djna.debug_load.jna=true -jar your-program.jar
-Djna.debug_load=true
:打印 native 库(如libjnidispatch.so
、user32.dll
等)的加载过程、搜索路径、是否成功加载等信息。-Djna.debug_load.jna=true
:额外打印 JNA 自身核心库(如jnidispatch
)的加载细节。
效果示例:
启用后会在控制台输出类似日志:
JNA: Looking in classpath from sun.misc.Launcher$AppClassLoader@18b4aac2 for /com/sun/jna/win32-x86-64/jnidispatch.dll
JNA: Found library resource at jar:file:/path/to/jna-5.14.0.jar!/com/sun/jna/win32-x86-64/jnidispatch.dll
JNA: Extracting library to C:\Users\user\AppData\Local\Temp\jna-12345\jna12345.dll
JNA: Loaded library jnidispatch
JNA: Added native methods for com.sun.jna.Native
2. 通过日志框架配置(适合更精细控制)
如果项目使用 java.util.logging
、Log4j
或 SLF4J
等日志框架,可通过配置 JNA 相关包的日志级别为 DEBUG
或 TRACE
,获取更详细的内部调用日志。
(1)使用 java.util.logging
(JDK 内置):
创建日志配置文件
logging.properties
:# 开启 JNA 相关包的 DEBUG 日志 com.sun.jna.level = FINEST com.sun.jna.platform.level = FINEST# 输出到控制台 handlers = java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level = FINEST java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
启动时指定配置文件:
java -Djava.util.logging.config.file=logging.properties -jar your-program.jar
(2)使用 Log4j 2(需项目依赖 Log4j):
在 log4j2.xml
中添加:
<Logger name="com.sun.jna" level="debug" additivity="false"><AppenderRef ref="Console"/>
</Logger>
<Logger name="com.sun.jna.platform" level="debug" additivity="false"><AppenderRef ref="Console"/>
</Logger>
(3)使用 SLF4J + Logback:
在 logback.xml
中添加:
<logger name="com.sun.jna" level="DEBUG"/>
<logger name="com.sun.jna.platform" level="DEBUG"/>
3. 代码中动态开启(适用于特定场景)
如果需要在代码运行时动态开启调试日志,可通过 System.setProperty()
方法设置:
java运行
public class JnaDebugExample {static {// 动态开启 JNA 调试日志System.setProperty("jna.debug_load", "true");System.setProperty("jna.debug_load.jna", "true");}public static void main(String[] args) {// 你的 JNA 调用代码}
}
注意:系统属性需在 JNA 类加载前设置(如放在 static
代码块中),否则可能不生效。
日志内容说明
开启 DEBUG 后,JNA 会输出以下关键信息:
- 搜索 native 库的路径(包括系统路径、JNA 内置路径、用户指定路径);
- 库文件的提取、加载过程(成功 / 失败原因);
- 函数映射、参数转换、调用结果等细节(仅高级日志可见)。
这些信息对于排查 UnsatisfiedLinkError
、库加载失败、函数调用异常等问题非常有用。
其他:
检查JNA库是否完整:
可以通过验证其包含的本地库文件、版本兼容性及功能可用性来判断。以下是具体方法:
1. 检查 JNA JAR 包的完整性
JNA 库的核心是jna.jar
(或jna-platform.jar
),其内部包含了各平台的本地库(如.so
、.dll
、.dylib
)。若 JAR 包损坏或不完整,会导致本地库缺失。
检查步骤:
查看 JAR 包包含的文件:
使用unzip
或jar
命令列出 JAR 包内容,确认包含对应平台的本地库:# 以jna-5.14.0.jar为例 unzip -l jna-5.14.0.jar | grep -E "linux|win32|darwin" # 过滤常见平台的库#正常输出示例(64 位 Linux 系统应包含的文件): com/sun/jna/linux-x86-64/libjnidispatch.so # Linux 64位 com/sun/jna/win32-x86-64/jnidispatch.dll # Windows 64位 com/sun/jna/darwin/libjnidispatch.jnilib # macOS
若缺失对应平台的
libjnidispatch.*
文件,说明 JAR 包不完整。验证 JAR 包的校验和:
若从 Maven 仓库下载,可对比官方提供的校验和(MD5/SHA),确认文件未被篡改或损坏:
# 计算本地JAR包的MD5
md5sum jna-5.14.0.jar# 对比Maven仓库的官方MD5(如从https://mvnrepository.com/下载页面获取)
2. 检查 JNA 库与系统架构的匹配性
JNA 的本地库与系统架构(32 位 / 64 位)强相关,若不匹配,会导致加载失败。
检查步骤:
确认系统架构:
uname -m # Linux/macOS:x86_64(64位)、i386(32位) # Windows(PowerShell): [Environment]::Is64BitOperatingSystem # 输出True表示64位
确认 JNA 包含对应架构的库:
结合步骤 1 的输出,检查是否有与系统架构匹配的本地库:- 64 位系统需包含
linux-x86-64
、win32-x86-64
或darwin-aarch64
(M1/M2 macOS)目录下的库; - 32 位系统需包含
linux-x86
、win32-x86
目录下的库3. 通过代码测试 JNA 功能是否正常
编写一个简单的 Java 程序,测试 JNA 是否能正常加载本地库并调用系统函数,验证其完整性。
测试代码示例:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;// 定义一个简单的系统函数接口(调用C标准库的printf)
nterface CLibrary extends Library {CLibrary INSTANCE = Native.load(Platform.isWindows() ? "msvcrt" : "c", CLibrary.class);void printf(String format, Object... args);
}public class JnaTest {public static void main(String[] args) {try {// 调用printf打印信息,验证JNA是否正常工作CLibrary.INSTANCE.printf("JNA库加载成功!系统架构:%s%n", Platform.ARCH);} catch (Exception e) {System.err.println("JNA库不完整或加载失败:" + e.getMessage());e.printStackTrace();}}
}
运行测试:
- 将测试代码与
jna.jar
放在同一目录; - 编译并运行:
javac -cp jna-5.14.0.jar JnaTest.java
java -cp .:jna-5.14.0.jar JnaTest # Linux/macOS
# 或 Windows:
java -cp .;jna-5.14.0.jar JnaTest
结果判断:
- 若输出
JNA库加载成功!系统架构:x86_64
→ 库完整且正常; - 若抛出
UnsatisfiedLinkError
且提示 “找不到库” → 库不完整或架构不匹配。 4. 检查依赖库是否完整
JNA 的本地库依赖系统底层库(如
glibc
),即使 JNA 本身完整,若系统缺少依赖,也会导致加载失败。检查步骤:
提取 JNA 的本地库(以 Linux 为例):
# 从JAR包中提取64位Linux的libjnidispatch.so
unzip -j jna-5.14.0.jar com/sun/jna/linux-x86-64/libjnidispatch.so -d /tmp/
- 检查该库的依赖是否缺失:
ldd /tmp/libjnidispatch.so
- 正常输出(所有依赖均显示路径):
linux-vdso.so.1 (0x00007ffd7f7f7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8b8d200000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8b8d420000)
- 异常输出(含
not found
):
libc.so.6 => not found # 说明缺少glibc库
#若有依赖缺失,需安装对应系统库(如libc6,参考前文的依赖安装方法)。
总结
检查 JNA 库是否完整的核心步骤:
- 验证 JAR 包包含对应平台的本地库(
libjnidispatch.*
); - 确认本地库与系统架构(32/64 位)匹配;
- 通过测试代码验证 JNA 能否正常调用系统函数;
- 检查本地库的系统依赖是否完整。
若以上步骤均通过,则 JNA 库完整;若某一步失败,需针对性修复(如重新下载 JAR 包、安装依赖库)。