.so 庫可正常 System.load,但特定庫拋出 UnsatisfiedLinkError: dlopen failed: library not found 或 JNI_OnLoad not found。System.loadLibrary (不帶路徑) 同樣失敗。Android 動態庫加載機制:
System.load 打開庫文件,調用其 JNI_OnLoad 函數。JNI_OnLoad 中通常調用 RegisterNatives 註冊 JNI 方法映射表。RegisterNatives 要求 **Java 端對應的 native 方法必須已聲明且簽名完全一致**。若 Java 類缺少某個 native 方法聲明,或簽名不匹配 (參數類型、返回類型、方法名),RegisterNatives 失敗,導致 JNI_OnLoad 返回錯誤碼,系統隨即卸載庫,拋出「庫未找到」或「符號缺失」誤導性錯誤。# Linux/Mac
nm -D yourlib.so | grep JNI
# 或
objdump -T yourlib.so | grep Java
# Windows (使用 GNU 工具鏈)
dumpbin /EXPORTS yourlib.dll | findstr Java
輸出示例:Java_com_example_MyClass_nativeMethod — 對應 Java 類 com.example.MyClass 的 nativeMethod。
確保 **每一個導出的 JNI 函數在 Java 類中都有對應的 native 聲明**,且:
jint↔int、jstring↔String、jobject↔對應類、jarray↔數組類型。native 聲明。Outer$Inner),C++ 符號需用 Outer_00024Inner (美元符號轉義)。package com.example;
public class MyClass {
static {
System.loadLibrary("mylib"); // 或 System.load("/full/path/libmylib.so")
}
// 對應 C++: Java_com_example_MyClass_init
public native int init(String configPath);
// 對應 C++: Java_com_example_MyClass_processData
public native byte[] processData(byte[] input, int mode);
// 切勿遺漏任何 C++ 導出的 JNI 函數對應聲明
}
JNI_OnLoad 中添加日誌輸出每個 RegisterNatives 結果。adb logcat | grep -i jni 觀察詳細錯誤信息 (如 RegisterNatives failed for ...)。**「同目錄其他庫能加載,只有這個不能」的核心原因,90% 是 Java 端 JNI 方法聲明缺失或簽名不匹配導致 RegisterNatives 失敗,而非文件系統問題。** 重點檢查 Java 與 C++ 符號表的一致性,補全聲明即可解決。