Performance JNI-将表示基本Java对象(布尔)的jobject转换为本机基本类型(bool)

Performance JNI-将表示基本Java对象(布尔)的jobject转换为本机基本类型(bool),performance,java-native-interface,android-ndk,Performance,Java Native Interface,Android Ndk,我想我设法把大部分问题都写进了这篇文章的标题中 我在我的本机C++代码中从java中提取一个对象: jobject valueObject = env->CallObjectMethod(hashMapObject, hashMapGetMID, keyObject); 我可以使用以下方法检查返回对象是否为本机类型之一: jclass boolClass = env->FindClass("java/lang/Boolean"); if(env->IsInstanceOf(v

我想我设法把大部分问题都写进了这篇文章的标题中

<>我在我的本机C++代码中从java中提取一个对象:

jobject valueObject = env->CallObjectMethod(hashMapObject, hashMapGetMID, keyObject);
我可以使用以下方法检查返回对象是否为本机类型之一:

jclass boolClass = env->FindClass("java/lang/Boolean");
if(env->IsInstanceOf(valueObject, boolClass) == JNI_TRUE) { }
因此,我现在有一个jobject,我知道它是一个布尔值(注意大写的B)-问题是,什么是最有效的方法(考虑到我的本机代码中已经有了jobject)将其转换为
bool
。打字不起作用,这是有道理的

尽管上面的例子是一个布尔值,我还是想转换字符->字符,短->短,整数->整数,浮点->浮点,双->双


(一旦我实现了它,我会发布一个答案,这个答案是Boolean.booleanValue())

如果我没有更多的输入,这就是我要使用的解决方案。希望这不是很难,但了解JNI我认为可能是:

    if     (env->IsInstanceOf(valueObject, boolClass)           == JNI_TRUE)
    {
        jmethodID booleanValueMID   = env->GetMethodID(boolClass, "booleanValue", "()Z");
        bool booleanValue           = (bool) env->CallBooleanMethod(valueObject, booleanValueMID);
        addBoolean(key, booleanValue);
    }
    else if(env->IsInstanceOf(valueObject, charClass)           == JNI_TRUE)
    {
        jmethodID characterValueMID  = env->GetMethodID(charClass, "charValue", "()C");
        char characterValue          = (char) env->CallCharMethod(valueObject, characterValueMID);
        addChar   (key, characterValue);
    }

一般来说,我编写jni是为了获得更好的性能。 如何获得更好的性能?使用asm、基元类型和很少的方法调用。 我建议设计您的方法返回类型可以在c/c++中使用,例如 jint、jlong、jboolean、jbyte和jchar等

冗余函数调用和转换将导致执行效率低下和无法维护。

您有两种选择

选项#1是您在自我回答中所写的:使用为每个类定义的公共方法提取原语值

选项#2速度更快,但并不严格合法:直接访问内部字段。对于Boolean,这将是Boolean.value。对于每个基本框类,“value”字段都有一个fieldID,您只需直接读取该字段。(JNI欣然忽略了它被声明为私有的事实。您还可以写入“final”字段,并执行其他属于“really bad idea”类别的操作。)

“value”字段的名称不太可能更改,因为这会破坏序列化。所以官方不建议这样做,但实际上,如果你需要的话,你可以不受惩罚

无论哪种方式,您都应该缓存jmethodID/jfieldID值,而不是每次都查找它们(查找成本相对较高)

您还可以使用成本较低的IsSameObject函数而不是IsInstanceof,因为box类是“final”类。这需要进行额外的GetObjectClass调用以获取valueObject的类,但在进行各种比较之前只需执行一次


顺便说一句,小心使用“char”。在上面的示例中,您正在将CallCharMethod(16位UTF-16值)的结果强制转换为char(8位值)。记住,查尔jchar(除非您以某种方式配置为宽字符),long!=jlong(除非您使用64位long进行编译)。

我选择动态代码而不是性能。运行时的值可以是任何基本类型-这就是为什么我试图找到将jobject转换为bool/char/int等的最佳方法,而不必通过JNI检查其类型和调用。在java级别执行动态和灵活的操作更好。我想是的,我也是!但是我不能选择在何处执行某些逻辑。如何在FindClass或GetMethodID jni调用中使用
jint、jlong、jboolean、jbyte
?那会编译吗?很好的回答,谢谢!很多有用的信息我都不知道。你有没有推荐一种特定的资源,或者是经过实践检验的“血、汗、泪”方法你在这里所问的那些事情可能是从书本上学不到的。如果你有时间写你自己的虚拟机,你肯定会学到很多;如果没有这一点,只需编写大量代码,然后尝试找出它被破坏的原因。:-)为什么不在Java代码中处理类型转换和取消装箱呢?