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

Android平台加载liboqs.so后出现Native方法未找到异常的求助

解决JNI方法未找到的UnsatisfiedLinkError问题

你已经成功加载了liboqs.so,但核心问题在于你编译的liboqs库中没有包含liboqs-java的JNI绑定代码——liboqs本身是纯C密码库,而liboqs-java的c/文件夹里是专门连接Java与liboqs的JNI封装代码,这些代码没被编译到你的liboqs.so中,导致Java调用Native方法时找不到实现。

下面是具体的解决步骤:

1. 确认JNI方法签名与C实现匹配

先验证你的liboqs.so中是否确实缺少对应的JNI方法符号:

  • 从jniLibs/x86_64/中复制出liboqs.so,使用NDK自带的nm工具检查:
    # 替换成你本地NDK路径下的x86_64 nm工具
    $NDK_PATH/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android-nm -D liboqs.so | grep max_number_sigs
    

如果没有输出,说明这个JNI方法确实不在库中,接下来需要把liboqs-java的JNI代码编译进去。

2. 配置NDK编译脚本(推荐用CMakeLists.txt)

你需要创建一个CMake配置文件,将liboqs-java的c/文件夹下所有JNI封装代码编译进去,并链接到liboqs库。

示例CMakeLists.txt配置

将文件放在src/main/cpp/CMakeLists.txt(如果你的JNI代码在src/main/c/,路径要对应调整):

cmake_minimum_required(VERSION 3.10.2)

# 1. 引入预编译的liboqs.so
add_library(liboqs SHARED IMPORTED)
set_target_properties(liboqs PROPERTIES
        IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/liboqs.so
        # 引入liboqs的头文件,假设你把liboqs的include目录放在src/main/c/include/
        INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/src/main/c/include)

# 2. 编译liboqs-java的JNI封装代码
add_library(oqs-jni SHARED
        src/main/c/sigs.c
        src/main/c/key_exchange.c
        src/main/c/common.c
        src/main/c/kem.c
        src/main/c/sig.c
        # 把liboqs-java c/文件夹下所有.c文件都列在这里
        )

# 3. 链接依赖库
target_link_libraries(oqs-jni
        liboqs
        log  # Android日志库,JNI中打日志需要
        android)

同步build.gradle配置

在app模块的build.gradle中添加CMake支持:

android {
    ...
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                abiFilters 'x86_64' // 匹配你的模拟器架构,需其他ABI可自行添加
                cppFlags "-std=c99" // liboqs依赖C99标准
            }
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt" // 指向你的CMake配置文件路径
        }
    }
    // 确保jniLibs和JNI代码目录被正确识别
    sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/jniLibs']
            jni.srcDirs = ['src/main/c'] // 你的JNI代码所在目录
        }
    }
}

3. 修改Java中的库加载逻辑

现在编译出的是liboqs-jni.so,需要先加载依赖的liboqs.so,再加载包含JNI绑定的库:

public static void loadNativeLibrary() {
    System.out.println("Loading liboqs.so for: " + Build.CPU_ABI + "...");
    System.loadLibrary("oqs");
    System.loadLibrary("oqs-jni"); // 加载包含JNI绑定实现的库
}

如果你修改CMake把JNI代码直接编译进liboqs.so,则只需要保留原来的System.loadLibrary("oqs")即可。

4. 验证编译结果

重新编译项目后,检查app/build/intermediates/cmake/debug/obj/x86_64/下的liboqs-jni.so,再次用nm命令查看是否包含Java_org_openquantumsafe_Sigs_max_1number_1sigs符号,有输出则说明编译成功。

额外检查点

  • 确保liboqs-java的JNI代码中的包名完全匹配Java类的包名(org.openquantumsafe),JNI方法名必须严格遵循Java_包名_类名_方法名格式,原方法名中的下划线要用_1代替。
  • 检查JNI方法的参数和返回值与Java中的Native方法完全一致:比如max_number_sigs()是无参数的int方法,C中的实现必须是JNIEXPORT jint JNICALL Java_org_openquantumsafe_Sigs_max_1number_1sigs(JNIEnv *env, jclass clazz)。
  • 确认Android模拟器的ABI与你编译的库ABI完全匹配(x86_64),避免架构不兼容。

内容的提问来源于stack exchange,提问作者Taimoor Ahmad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:22:47