JNI是否要求根据参数类型对参数进行排序?

Does JNI requires ordering of arguments based on argument types

本文关键字:参数 排序 类型 JNI 是否      更新时间:2023-10-16

我试图将一些JNI代码集成到我的应用程序中,该应用程序从web服务接收数据并在JNI层中解析它,从那里我尝试通过传递从web服务接收的一些参数来调用Java层中定义的方法。下面是函数和方法的流程:

为jclass和jmethodID定义变量:

    static jclass userInfo                      = NULL ;
    static jmethodID create_user_info = NULL ;

Struct定义在c层保存值

    struct User_Info {            
        long userId; // 1
        std::string firstName; // 2
        std::string lastName; // 3
        bool follow; // 4
    };

这个函数有问题。此函数在从webservice接收数据、解析数据并创建结构User_Info

后调用。
    static jobject createJavaObject(JNIEnv *env, const User_Info& info) {
        if(!userInfo){
            userInfo = (jclass)env->NewGlobalRef(env->FindClass("com/model/UserInfo"));
            assert(userInfo != NULL);
            create_user_info = env->GetStaticMethodID(userInfo, "createUserInfo", "("
                "I" // userId // 1
                "Ljava/lang/String;" // firstName // 2
                "Ljava/lang/String;" // lastName // 3
                "Z" // follow // 4
                ")Lcom/model/UserInfo;");
            assert(create_user_info != 0);
        }
        jstring firstName = cast<jstring>(env, info.first_name); // cast function just converts string to jstring 
        assert(firstName != NULL);
        jstring lastName = cast<jstring>(env, info.last_name);  // cast function just converts string to jstring 
        assert(lastName != NULL);
        
        // ISSUE IS WITH FOLLOWING CALL
        jobject res = env->CallStaticObjectMethod(userInfo, create_user_info,
                                                                  info.userId, // 1
                                                                  firstName, // 2
                                                                  lastName, // 3
                                                                  info.follow // 4 
                                                                  );
        env->DeleteLocalRef(firstName);
        env->DeleteLocalRef(lastName);
        return res;
    }
    
    
    // cast function:
    
    jstring cast<jstring, char const *>()(JNIEnv *env, char const *s)         {
        if (!s) return 0;
        jbyteArray bytes = env->NewByteArray(strlen(s));
        env->SetByteArrayRegion(bytes, 0, strlen(s), (jbyte*)s);
        jmethodID midStringCtor = env->GetMethodID(clsString, "<init>", "([BLjava/lang/String;)V");
        jstring ret = (jstring)env->NewObject(clsString, midStringCtor, bytes, encoding);
        env->DeleteLocalRef(bytes);
        return ret;
    }
    
Java方法:

@Native
private static UserInfo createUserInfo(
                            int userId, // 1
                            String firstname, // 2
                            String lastname, // 3
                            boolean follow // 4
                        ) {
    UserInfo info = new UserInfo();
    info.userId = userId;
    info.firstname = firstname;
    info.lastname = lastname;
    info.follow = follow;
    return info;
}   

问题是,当我运行代码,我得到以下错误:

JNI ERROR(应用程序错误):预期的jboolean(0/1),但得到的值为1048605作为参数4到com.model.UserInfo。createUserInfo (int, . lang。字符串,. lang。字符串,布尔)

当我改变java方法和jni函数中的参数顺序并在int 'userId'之后保留布尔'follow'时,则不会发生问题。

我的问题是:

JNI是否要求根据参数的类型排序例如,int形参在long/boolean前面,或基本形参在对象前面等。

如果是,是否有任何参考/文档建议,如果没有,那么为什么我的代码在改变参数顺序后工作?

是否需要在JNI函数参数中保持原语和对象的某种顺序

这个问题很难理解。所需要的是保持JNI方法方法声明与在包含本机方法的类上运行javah所产生的声明一致。

static jclass userInfo                      = NULL ;

这里有一个bug。保留对jobjectsjclasses的静态引用是无效的,除非它们是全局引用或弱引用。