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

如何修改字节数组并通过JNI从C++向Java传输?附函数代码

修改字节数组并通过JNI从C++传递到Java的实现指南

先把你给出的代码片段整理成可读性更强的格式:

void FrameReceived(int width, int height, const char *rawImageBytes, int size, jboolean remote) {
    if(size == 0) return;
    jboolean isAttached;
    JNIEnv *env;
    jint jParticipant;
    jint jWidth;
    jint jHeight;
    jbyte *jRawImageBytes;
    jbyte *modifiedRawImageBytes;
    jbyteArray Array;

    env = getJniEnv(&isAttached);
    if (env == NULL) goto FAIL0;

    //LOGE(".... **** ....TRYING TO FIND CALLBACK");
    if(remote) {
        if(frameReceivedRemoteMethod == NULL) 
            frameReceivedRemoteMethod = getApplicationJni...
        // 代码未完整展示,后续逻辑补充如下
    }

    // 这里是核心逻辑实现区
FAIL0:
    // 资源清理逻辑
}

接下来我给你补充完整修改字节数组并传递到Java的关键步骤,都是实际项目里常用的写法:

1. 创建Java字节数组并准备修改

首先要把C++里的原始字节数据转换成Java能识别的jbyteArray,同时拿到可修改的原生指针:

// 跳过前面的环境检查,直接写核心逻辑
jbyteArray jImageArray = env->NewByteArray(size);
if (jImageArray == nullptr) {
    LOGE("Failed to create jbyteArray");
    goto FAIL0;
}

// 获取可读写的原生字节指针,第二个参数是是否拷贝(传nullptr让JNI自动处理)
jbyte* nativeBuffer = env->GetByteArrayElements(jImageArray, nullptr);
if (nativeBuffer == nullptr) {
    LOGE("Failed to get native buffer from jbyteArray");
    env->DeleteLocalRef(jImageArray);
    goto FAIL0;
}

2. 执行字节数组的修改操作

现在你可以直接操作nativeBuffer指针来修改数据,比如做图像像素处理、字节反转、加密等,这里给个示例:

// 示例1:直接拷贝原始数据后修改部分内容
memcpy(nativeBuffer, rawImageBytes, size);
// 比如把所有偶数索引的字节置0
for (int i = 0; i < size; i += 2) {
    nativeBuffer[i] = 0;
}

// 示例2:直接对原始字节做转换后写入
for (int i = 0; i < size; i++) {
    // 比如做像素值反转(适合灰度图)
    nativeBuffer[i] = static_cast<jbyte>(0xFF - static_cast<unsigned char>(rawImageBytes[i]));
}

3. 提交修改并调用Java方法传递数组

修改完成后要释放指针并提交修改,然后调用你获取到的Java回调方法:

// 提交修改并释放指针,第三个参数传0表示提交修改并释放内存
env->ReleaseByteArrayElements(jImageArray, nativeBuffer, 0);

// 调用Java端的回调方法,假设你的方法签名是void onRemoteFrameReceived(int, int, byte[])
if (frameReceivedRemoteMethod != nullptr) {
    env->CallVoidMethod(applicationObj, frameReceivedRemoteMethod, width, height, jImageArray);
    // 检查JNI调用是否抛出异常
    if (env->ExceptionCheck()) {
        env->ExceptionClear();
        LOGE("Failed to call Java frame received method");
    }
}

// 记得释放局部引用,避免JNI局部引用表溢出
env->DeleteLocalRef(jImageArray);

4. 完善资源清理逻辑

在FAIL0标签处要处理线程分离和资源释放:

FAIL0:
    // 如果是动态附加的线程,要分离
    if (isAttached == JNI_TRUE && gvm != nullptr) {
        gvm->DetachCurrentThread();
    }

几个关键注意事项

  • 局部引用管理:JNI中创建的jbyteArray、jobject等都是局部引用,必须用DeleteLocalRef释放,否则会导致内存泄漏。
  • 线程安全:JNIEnv是线程专属的,绝对不能跨线程传递,所以每次都要通过getJniEnv获取当前线程的环境。
  • 异常检查:每次调用JNI方法后最好检查是否有异常,及时清理避免影响后续逻辑。

内容的提问来源于stack exchange,提问作者rosu alin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:03:16