1

我正在编写一个使用 JNI 的文本/VoIP 程序的 C++/Native 端。目前,Java 代码可能会定期调用 C++ 端的三个函数。调用函数的频率将取决于用户发送/接收文本消息的频率以及他们的朋友在改变他们的存在/状态方面的活跃程度。这三个函数中的每一个都遵循下面的伪代码,我不确定在函数中“全球化”任何东西是否明智(甚至可能)。

JNIEnv *env;
if (jvm_->GetEnv((void**) &env, JNI_VERSION_1_6) < 0)
{
[print error and return]
}

jclass stringclass = env->FindClass("java/lang/String"); // Same for all 3
jstring passinfo = env->NewStringUTF([str-info-to-pass]); // Different for all 3
jclass cls = env->FindClass([directory to calling Java function class]); // Same for all 3
[check if cls found, print error if not found and return]

jmethodID methID = env->GetStatisMethodID([arguments for the function]); // Different for all 3
[check if methID found, print error if not found and return]

jobjectArray args = env->NewObjectArray([arguments to build argument structure being passed to function]);
[call Java function, passing right arguments]

我在想我应该/应该能够将 jclass stringclass、jclass cls 和 JNIEnv *env 从函数中移出,并使它们成为在 JNI_OnLoad 函数调用期间设置的全局变量。这可能/可取吗?这些值是否会与 OnLoad 函数与这些函数有所不同?我是否应该将它们实例化为全局变量并在函数调用中每次都设置它们?而且,做这些真的会显着提高性能吗?

4

2 回答 2

2

可能,是的。明智的,这取决于。为自己定义什么是“显着数量”。您期望 JNI 调用的节奏是什么?我认为您可以从每秒 10 次以上的调用开始看到缓存的一些可衡量的影响。这是一个案例吗?无论如何,以我个人的经验,出色的缓存可以清理代码,使其更短且更具可读性。所以无论如何我都会给出一些建议。

的缓存结果FindClass,是的。通常任何可重用和“静态”的东西,你通过符号名称查找的内容 - 这引入了符号查找的惩罚,这与简单地使用已经缓存的指针相反。Liang JNI 的书还谈到了字段和方法 ID,所以你可以GetStaticMethodID申请。jmethodID在可以直接缓存结果的意义上更简单Get(Static)MethodID:它对任何进一步的调用都有效。与FindClass返回本地引用不同,因此对于有效的缓存(并使其jmethodID真正持久化),您必须NewGlobalRef从中创建 - 并在适当时将其删除。JNI_OnLoad 教程中有一个很好的综合示例. 另一方面,缓存 JNIEnv 没有意义,每次 JNI 调用都会再次获取它。如果您碰巧从另一个线程调用 JNI 方法,而不是您从中缓存的线程,则缓存的 JNIEnv 也将无效。

于 2012-08-15T17:54:50.310 回答
0

你不应该担心性能。目前,我开发了一个使用本地编解码器的 voip 客户端。这意味着每个 rtp 数据包都会调用 JNI(每 20 毫秒两次,因为编码和解码都是如此),每次调用也会传递 JNIEnv。这个变量只是一个指针。在这些情况下,在低端设备上,JNI 调用所消耗的 CPU 使用率低于 1%,所以如果你只需要发短信,你完全不用担心。

于 2014-01-29T13:07:23.070 回答