多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
在JNI中,你可以按照如下步骤调用构造函数,就像调用普通的对象实例函数那样。要获取MethodID,只需要使用"<init>作为函数名,将"V"作为函数返回值类型构造一个方法描述符即可。 你可以通过将方法ID传递给像NewObject这样的JNI函数来调用构造函数。以下函数实现了与JNI函数NewString同样的功能:从C缓冲区中存储的Unico字符串构造一个java.lang.String对象: ~~~ #include <jni.h> #ifdef __cplusplus extern "C" { #endif jstring MyNewString(JNIEnv *env, jchar *chars, jint len) { jclass stringClass; jmethodID cid; jcharArray elemArr; jstring result; stringClass = (*env)->FindClass(env, "java/lang/String"); if(!stringClass){ return 0; /* exception thrown */ } /* Get the method ID for the String(char[]) constructor */ cid = (*env)->GetMethodID(env, stringClass, "<init>", "([C)V"); if(!cid) { return 0; /* exception thrown */ } /* Create a char[] that holds the string characters */ elemArr = (*env)->NewCharArray(env, len); if(!elemArr) { return 0; /* exception thrown */ } (*env)->SetCharArrayRegion(env, elemArr, 0, len, chars); /* Construct a java.lang.String */ result = (*env)->NewObject(env, stringClass, cid, elemArr); /* Free local references */ (*env)->DeleteLocalRef(env, elemArr); (*env)->DeleteLocalRef(env, stringClass); return result; } #ifdef __cplusplus } #endif ~~~ 这个函数还是有点复杂的,我来给大家详细解释下。 首先,FindClass查找到java.lang.String对应的类引用。 然后,GetMethodID返回了String类构造函数String(char[] chars)对应的方法ID,之后再调用NewCharArray分配了一个字符串数组,用于存储所有的字符串元素。最后JNI函数NewObject调用方法ID对应的构造函数,NewObject调用需要三部分参数:需要构建的对象对应的类引用, 构造函数方法ID, 构造函数需要的参数列表。 DeleteLocalRef函数调用允许虚拟机释放elemArr和stringClsss使用的资源.第5.2.1节会详细介绍为什么要使用DelectLocalRef以在什么时候使用. String也是对象.这个实例也进一步说明了这点.然而,这个示例也带给我们一个问题,我们已经能够使用其他的JNI函数实现相同的功能,那为什JNI却要提供NewString这样的内置函数呢?根本原因是内置的字符串操作函数更加高效.字符串算得上使频最高的对象,所以专门为它提一套API支持也是值得的. 我们也可以使用CallNonvirtualVoidMethod函数调用构造函数,但是首先我们需要通过调用AllocObject函数创建一个未初始化的对象.上边实例中的NewObject调用: `result = (*env)->NewObject(env,stringClass, cid, elemArr);` 可以用一个AllocObject和CallNonvirtualVoidMethod替代: ~~~ result = (*env)->AllocObject(env, stringClass); if (result) { (*env)->CallNonvirtualVoidMethod(env, result, stringClass, cid, elemArr); /* we need to check for possible exceptions */ if((*env)->ExceptionCheck(env)) { (*env)->DeleteLocalRef(env, result); result = NULL; } } ~~~ AllocObject用于创建一个未初始化的对象,在使用的时候必须多加小心来保证一个构造函数在每个对象最多只能被调用一次.Native代码不应当在同一个对象上多次调用构造函数. 有的时候你会发现先分配一个未初始化对象,之后再在合适的时机调用构造函数会很有用(这个有点像c++的placement new).但是大多数情况下,你都应当使用NewObject来创建对象而不是使用更加容易产生错误的AllocObject/CallnonvirtualVoidMethod函数对.