Android 7 中JNI的使用有了些新特性需要注意。
我们来看看JNI调用流程
Parcel.java中的nativeWriteInt方法是如何调用到native层的呢?
frameworks/base$ vi ./core/java/android/os/Parcel.java
public final void writeInt(int val) {
nativeWriteInt(mNativePtr, val);
}
在开机的时候,进行了JNI方法注册。
在frameworks/base/core/jni/android_os_Parcel.cpp中有
const char* const kParcelPathName = "android/os/Parcel"; int register_android_os_Parcel(JNIEnv* env) { jclass clazz = FindClassOrDie(env, kParcelPathName); gParcelOffsets.clazz = MakeGlobalRefOrDie(env, clazz); gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, clazz, "mNativePtr", "J"); gParcelOffsets.obtain = GetStaticMethodIDOrDie(env, clazz, "obtain", "()Landroid/os/Parcel;"); gParcelOffsets.recycle = GetMethodIDOrDie(env, clazz, "recycle", "()V"); return RegisterMethodsOrDie(env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods)); }
android.os.Parcel(android/os/Parcel)类中的nativeWriteInt方法对应android_os_Parcel.cpp中的android_os_Parcel_writeInt方法 static const JNINativeMethod gParcelMethods[] = { {"nativeDataSize", "!(J)I", (void*)android_os_Parcel_dataSize}, {"nativeDataAvail", "!(J)I", (void*)android_os_Parcel_dataAvail}, {"nativeWriteByteArray", "(J[BII)V", (void*)android_os_Parcel_writeNative}, {"nativeWriteBlob", "(J[BII)V", (void*)android_os_Parcel_writeBlob}, {"nativeWriteInt", "!(JI)V", (void*)android_os_Parcel_writeInt}, android_os_Parcel_writeInt方法里调用了C++层的Parcel的处理 static void android_os_Parcel_writeInt(JNIEnv* env, jclass clazz, jlong nativePtr, jint val) { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { const status_t err = parcel->writeInt32(val); if (err != NO_ERROR) { signalExceptionForError(env, clazz, err); } } } 这样就通过JNI实现了Java层调用C++层的方法。 关于方法签名 "!(JI)V"中的!,后续我们将再进行分析说明 另外一个需要注意的地方就是JNI方法中的第二个参数可以是jclass,也可以是jobject static void android_os_Parcel_writeInt(JNIEnv* env, jclass clazz, jlong nativePtr, jint val) { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { const status_t err = parcel->writeInt32(val); if (err != NO_ERROR) { signalExceptionForError(env, clazz, err); } } } 里面是jclass clazz,而frameworks/base/core/jni/android_util_AssetManager.cpp里的 static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle) { ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle); theme->clear(); } 里面是jobject clazz 这个处理是虚拟机里进行的,我们在设计功能的时候,根据实际的需求来确定即可,如果需要获取对用的Java对象,就使用jobject
const char* const kParcelPathName = "android/os/Parcel"; int register_android_os_Parcel(JNIEnv* env) { jclass clazz = FindClassOrDie(env, kParcelPathName); gParcelOffsets.clazz = MakeGlobalRefOrDie(env, clazz); gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, clazz, "mNativePtr", "J"); gParcelOffsets.obtain = GetStaticMethodIDOrDie(env, clazz, "obtain", "()Landroid/os/Parcel;"); gParcelOffsets.recycle = GetMethodIDOrDie(env, clazz, "recycle", "()V"); return RegisterMethodsOrDie(env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods)); }