使用 JNI 从本机方法返回 null

2022-09-03 07:57:44

我有一些返回jbyteArray的本机代码(所以Java端的byte[]),我想返回null。但是,如果我简单地返回0代替jbyteArray,我会遇到问题。

更多信息:主要逻辑是在Java中,本机方法用于将一些数据编码为字节流。不要问..它必须像这样完成。最近,本机代码必须进行一些更改,现在它运行得非常慢。经过一些实验,包括在返回之前注释掉本机方法中的所有代码,事实证明返回0会导致速度变慢。当返回实际的jbyteArray时,一切都很好。

我的代码的方法签名:

在C++方面:

extern "C" JNIEXPORT jbyteArray JNICALL Java_com_xxx_recode (JNIEnv* env, jclass java_this, jbyteArray origBytes, jobject message)

在Java方面:

private static native byte[] recode(byte[] origBytes, Message message);

本机代码如下所示:

jbyteArray javaArray;
if (error != ERROR) {
    // convert to jbyteArray
    javaArray = env->NewByteArray((jsize) message.size);
    env->SetByteArrayRegion(java_array, 0, message.size, reinterpret_cast<jbyte*>(message.buffer()));
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
        error = ERROR;
    }
}
if (error == ERROR) {
    return 0; // Does NOT work - doesn't crash, just slows everything down horrible.
}
else {
    return javaArray; // Works perfectly.
}

有谁知道发生这种情况的任何原因?从本机方法返回 NULL 来代替 jbyteArray 是有效的,还是有另一个过程可以将 null 返回给 Java。不幸的是,我在谷歌上没有运气。

谢谢!

编辑:添加了其他信息。


答案 1

这是一个古老的问题,但我一分钟前也遇到了这个问题......

你在问题中说:

return 0; // Does NOT work - doesn't crash, just slows everything down horrible.

实际上,我只是尝试了一下,因为这是我的代码必须分配和返回的内容,除非发生错误(由与此主题无关的某些标准定义),在这种情况下,它必须返回空结果。jintArray

碰巧返回(定义为 )工作完美,并被解释为返回Java端。我没有注意到表演的任何降级。除非我错过了任何没有演员的回报,否则不会改变任何事情。NULL((void*)0)null0void *

所以我不认为这是你遇到减速的原因。 看起来很好。NULLnull

编辑

  • 我确认,返回值与表演无关。我刚刚测试了一个相同的代码,在一侧返回一个空值,另一个返回一个对象(a)。对于 大小为 0 的 a 和静态分配的几个 KB 的随机值,性能是相似的。jintArrayNULLjintArrayjintArray

  • 我还尝试更改调用方类字段的值,并使用大致相同的性能来反转 void。速度非常慢,可能是由于捕获该字段并设置它所需的反射代码。

  • 所有这些测试都是在Android下进行的,而不是在Java独立下进行的 - 也许这就是原因?(见评论):

    • 在 HAXM 下运行的 API 17 x86 仿真器
    • API 19,在相同条件下运行
    • 两个API 19物理设备 - 一个华硕平板电脑和一个Galaxy 5 - 在Dalvik下运行。

答案 2

你的代码中有一些不对称性引起了我的注意:你永远不会决定要返回的对象类型,除非返回“无”。显然,对象决定了如何分配 ,那么为什么不要求它返回某种空数组呢?在 jni 和 java 之间封送时,可能需要以特殊方式处理返回的 0。envjavaSrray


推荐