You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android构建遇UnsatisfiedLinkError,CMake加载.so库问题求助

问题:Android中加载Native库时出现java.lang.UnsatisfiedLinkError

我在构建指纹采集验证应用时遇到了两个相关错误:

  1. java.lang.UnsatisfiedLinkError:无法通过dalvik.system.PathClassLoader加载NativeMorphoSmartSDK_6.13.2.0-4.1
  2. 空指针类型的UnsatisfiedLinkError

我使用OpenSSL和第三方库实现功能,以下是我的CMake配置文件:

# For more information about using CMake with Android Studio, read the documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        src/main/cpp/native-lib.cpp )

add_library(openssl SHARED IMPORTED)
set_target_properties (openssl PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/lib/libcrypto.so )
set_target_properties (openssl PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/lib/libssl.so )
set_target_properties (openssl PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/lib/libidkit.so )
set_target_properties (openssl PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/lib/libjnidispatch.so )
set_target_properties (openssl PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/lib/libMSO100.so )
set_target_properties (openssl PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/lib/libNativeMorphoSmartSDK_6.13.2.0-4.1.so )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
include_directories(openssl-armeabi-v7a/include/)

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
        native-lib

        ${CMAKE_CURRENT_SOURCE_DIR}/openssl-armeabi-v7a/lib/libcrypto.a
        ${CMAKE_CURRENT_SOURCE_DIR}/openssl-armeabi-v7a/lib/libssl.a

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib} )

想请教:当前通过CMake加载.so文件的方式是否正确?还有哪些加载.so文件的方法?如何解决这个错误?


回答

嘿,我来帮你拆解下这个问题——你遇到的java.lang.UnsatisfiedLinkError基本是CMake配置的几个关键错误导致的,咱们一步步理清楚:

一、当前CMake配置的核心问题

你的配置里有几个明显的错误,直接导致了库加载失败:

  1. 重复覆盖导入库路径
    你把所有第三方.so都塞进了名为openssl的导入库,每次调用set_target_properties都会覆盖之前的IMPORTED_LOCATION值,最后只有libNativeMorphoSmartSDK_6.13.2.0-4.1.so会被CMake识别,其他像libcrypto.so、libssl.so这些库都被覆盖丢失了。每个第三方.so都得单独定义成一个导入库,不能共用一个目标名。

  2. 静态库与动态库混用冲突
    你在target_link_libraries里链接了静态版本的libcrypto.a和libssl.a,但同时又尝试导入它们的动态.so版本,这会让链接器混乱,直接引发加载错误。得统一用静态或动态版本,不能两边都沾。

  3. 硬编码架构导致适配问题
    你在include_directories里写死了armeabi-v7a,如果你的项目支持多架构(比如现在主流的arm64-v8a),其他架构下根本找不到头文件,自然会出问题。应该用${ANDROID_ABI}来动态匹配当前编译的架构。

二、修复后的CMake配置参考

我帮你调整了配置,你可以直接用:

cmake_minimum_required(VERSION 3.4.1)

# 定义你的主Native库
add_library(native-lib SHARED src/main/cpp/native-lib.cpp)

# 每个第三方动态库单独定义
add_library(crypto SHARED IMPORTED)
set_target_properties(crypto PROPERTIES
        IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libcrypto.so)

add_library(ssl SHARED IMPORTED)
set_target_properties(ssl PROPERTIES
        IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libssl.so)

add_library(idkit SHARED IMPORTED)
set_target_properties(idkit PROPERTIES
        IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libidkit.so)

add_library(jnidispatch SHARED IMPORTED)
set_target_properties(jnidispatch PROPERTIES
        IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libjnidispatch.so)

add_library(MSO100 SHARED IMPORTED)
set_target_properties(MSO100 PROPERTIES
        IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libMSO100.so)

add_library(MorphoSDK SHARED IMPORTED)
set_target_properties(MorphoSDK PROPERTIES
        IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libNativeMorphoSmartSDK_6.13.2.0-4.1.so)

# 动态匹配架构的头文件路径
include_directories(${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/include/)

# 找到系统log库
find_library(log-lib log)

# 把所有依赖库链接到你的主库
target_link_libraries(native-lib
        crypto
        ssl
        idkit
        jnidispatch
        MSO100
        MorphoSDK
        ${log-lib})

三、其他加载.so文件的方法

除了CMake,Android里还有几种常用的Native库加载方式:

  1. Gradle直接配置(最简单)
    不用写CMake,直接在app/build.gradle的android块里加这段,Gradle会自动打包jniLibs下的所有.so:
android {
    sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/jniLibs']
        }
    }
}

然后在Java代码里用System.loadLibrary("NativeMorphoSmartSDK_6.13.2.0-4.1")加载就行——注意要去掉前缀lib和后缀.so。

  1. 手动指定绝对路径加载
    如果你的库不在默认的jniLibs目录,也可以用绝对路径加载:
System.load("/data/data/com.your.package/files/libNativeMorphoSmartSDK_6.13.2.0-4.1.so");

不过这种方式要处理文件权限和不同设备的路径适配,一般不推荐在正式项目里用。

  1. 传统NDK的Android.mk/Application.mk
    这是比较老的构建方式,现在CMake更主流,但如果是维护旧项目可以用:
  • Android.mk用来定义库的编译、链接规则
  • Application.mk指定项目支持的CPU架构

四、额外排查小技巧

  • 检查架构兼容性:用readelf -h libxxx.so命令查看每个.so支持的架构,确保和你项目配置的架构一致(比如arm64-v8a、armeabi-v7a)。
  • 检查库的依赖:有些.so依赖其他库,用objdump -x libxxx.so | grep NEEDED可以查看它需要的依赖库,确保所有依赖都打包进了APK。
  • 注意加载顺序:如果库之间有依赖关系,得先加载依赖库,再加载主库。比如libNativeMorphoSmartSDK依赖libMSO100.so,那就要先调用System.loadLibrary("MSO100"),再加载SDK库。

内容的提问来源于stack exchange,提问作者Gajanand Swamy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:06:39