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

如何在Android中通过JNI调用带ByteArray参数的Kotlin/Native预构建共享库

问题:Kotlin/Native共享库JNI调用ByteArray参数崩溃问题

我正在构建Kotlin/Native库并在Android应用中使用,因需要代码混淆,选择预构建共享库而非.jar文件。目前已通过JNI成功调用简单的"Hello World"函数,但在实现接收ByteArray参数的readByteArray函数时遇到问题:不清楚如何构建Kotlin/Native生成的libshared_lib_kref_kotlin_ByteArray类型,尝试使用GetDirectBufferAddress和GetByteArrayElements均导致崩溃,求解决方法。


相关代码

Kotlin/Native代码

fun readByteArray(byteArray: ByteArray): String {
    val unsignedByteArray = byteArray.toUByteArray()
    var i = 0

    while (i < byteArray.size) {
        // Access the array
        val byte = unsignedByteArray[i].toUInt()
        i++
    }

    return "Done reading the array"
}

Android端NativeLib类代码

external fun readByteArray(byteArray: ByteArray): String

JNI C++待实现代码

extern "C" JNIEXPORT jstring JNICALL
Java_com_my_package_NativeLib_readByteArray(JNIEnv *env, jobject,
                                            jbyteArray byte_array) {
    libshared_lib_ExportedSymbols *lib = libshared_lib_symbols();
    // What to do here?
    return env->NewStringUTF(lib->kotlin.root.readByteArray(/* and here? */));
}

Kotlin/Native生成的头文件片段

typedef void* libshared_lib_KNativePtr;
...
typedef struct {
  libshared_lib_KNativePtr pinned;
} libshared_lib_kref_kotlin_ByteArray;
...
struct {
  struct {
    const char* (*readByteArray)(libshared_lib_kref_kotlin_ByteArray byteArray);
    const char* (*sayHello)();
  } root;
} kotlin;
...

解决方案

不能直接用JNI数组操作函数强转生成libshared_lib_kref_kotlin_ByteArray,必须通过Kotlin/Native提供的内存管理API创建对应Kotlin ByteArray实例,具体实现步骤如下:

  1. 获取JNI数组的原始数据指针和长度
  2. 调用Kotlin/Native生成的数组创建API生成Kotlin ByteArray对象
  3. 将对象指针封装为要求的结构体类型
  4. 调用目标函数后释放所有资源,避免内存泄漏

完整JNI实现代码:

extern "C" JNIEXPORT jstring JNICALL
Java_com_my_package_NativeLib_readByteArray(JNIEnv *env, jobject,
                                            jbyteArray byte_array) {
    libshared_lib_ExportedSymbols *lib = libshared_lib_symbols();
    
    // 1. 获取Java ByteArray的原始数据和长度
    jbyte* src_bytes = env->GetByteArrayElements(byte_array, nullptr);
    jsize byte_count = env->GetArrayLength(byte_array);
    
    // 2. 创建Kotlin/Native ByteArray实例
    libshared_lib_KNativePtr kotlin_byte_array = lib->kotlin.ByteArrayOf(src_bytes, byte_count);
    
    // 3. 封装为要求的结构体
    libshared_lib_kref_kotlin_ByteArray kref_byte_array;
    kref_byte_array.pinned = kotlin_byte_array;
    
    // 4. 调用Kotlin函数
    const char* result_str = lib->kotlin.root.readByteArray(kref_byte_array);
    
    // 5. 释放JNI数组引用
    env->ReleaseByteArrayElements(byte_array, src_bytes, JNI_ABORT);
    
    // 6. 转换结果为Java String
    jstring result = env->NewStringUTF(result_str);
    
    // 7. 释放Kotlin对象,避免内存泄漏
    lib->DisposeStablePointer(kotlin_byte_array);
    
    return result;
}

关键说明

  • 数组创建API:Kotlin/Native会自动生成ByteArrayOf这类数组创建函数,一般挂载在kotlin结构体下,可在完整生成的头文件中确认具体命名。
  • 内存管理:Kotlin/Native创建的对象必须用DisposeStablePointer释放;JNI数组引用必须通过ReleaseByteArrayElements释放。
  • 禁止直接强转:libshared_lib_kref_kotlin_ByteArray的pinned字段是Kotlin/Native内部稳定指针,不能直接赋值JNI数组指针,必须通过官方API生成。

内容的提问来源于stack exchange,提问作者Paul-Etienne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 11:26:35