在Android开发的世界里,Framework和JNI无疑是两个不可或缺的核心组件。Framework为Android应用提供了丰富的功能和稳定的运行环境,而JNI则允许Java代码与本地代码(如C/C++)进行交互。本文将通过深入分析Android 12.0.0_r34的代码,揭开Framework与JNI之间的神秘联系,并探讨它们在实际开发中的应用。
在Android Framework中,JNI(Java Native Interface)的动态注册是一个关键环节。通常,框架中使用的native函数都是通过动态注册的方式与Java层进行交互的。这种注册过程遵循一定的套路,使得开发者能够方便地调用本地代码。
以Parcel类为例,我们可以看到其中包含多个标记为native的方法。这些方法的动态注册过程可以通过Android源码中的jni定义来进一步了解。首先,我们可以在Parcel.java中找到这些native方法的声明:
publicfinalclassParcel{
privatestaticnative longnativeCreate();
privatestaticnative longnativeFreeBuffer(longnativePtr);
privatestaticnative voidnativeDestroy(longnativePtr);
}
接下来,在Android源码中,我们可以找到相应的jni定义:
// frameworks/base/core/jni/android_os_Parcel.cpp
# include"core_jni_helpers.h"
namespace android {
staticstructparcel_offsets_t{
jobject clazz;
jfieldID mNativePtr;
jmethodID obtain;
jmethodID recycle;
} gParcelOffsets;
staticjlongandroid_os_Parcel_create(JNIEnv* env, jobject clazz){
Parcel* parcel =newParcel();
return reinterpret_cast<jlong>(parcel);
}
staticvoidandroid_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz, jlong nativePtr){
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if(parcel !=NULL) {
parcel->freeData();
}
}
staticvoidandroid_os_Parcel_destroy(JNIEnv* env, jobject clazz, jlong nativePtr){
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
deleteparcel;
}
// ...
}
在源码中,我们还会发现一个名为register_android_os_Parcel
的函数,它负责完成所有JNI函数的动态注册。这个函数的内部实现涉及到两个关键步骤:首先,使用RegisterMethodsOrDie
函数完成所有JNI函数的动态注册;其次,提前使用JNIEnv找到后续cpp函数回调Java层时可能要用到的jclass、jfieldID或jmethodID,并将这些信息保存在一个全局结构体中。
// frameworks/base/core/jni/core_jni_helpers.h
# include<android_runtime/AndroidRuntime.h>
namespace android {
staticinlineintRegisterMethodsOrDie(JNIEnv* env,constchar* className,constJNINativeMethod* gMethods,intnumMethods){
intres = AndroidRuntime::registerNativeMethods(env, className, gMethods, numMethods);
LOG_ALWAYS_FATAL_IF(res <0,"Unable to register native methods.");
returnres;
}
}
那么,框架会在什么时候调用相应的register函数呢?答案依然在AndroidRuntime.cpp
中。首先,我们会在AndroidRuntime.cpp
中看到extern声明和一个全局数组:
// frameworks/base/core/jni/AndroidRuntime.cpp
usingnamespace android;
externintregister_android_opengl_jni_EGL14(JNIEnv* env);
externintregister_android_opengl_jni_EGL15(JNIEnv* env);
externintregister_android_opengl_jni_EGLExt(JNIEnv* env);
// ...
externintregister_android_os_MessageQueue(JNIEnv* env);
externintregister_android_os_Parcel(JNIEnv* env);
// ...
接下来,我们定义了一个名为REG_JNI
的结构体,用于存储注册函数的名称和对应的函数指针:
// frameworks/base/core/jni/AndroidRuntime.cpp
# ifdefNDEBUG
# defineREG_JNI(name) { name }
# else
# defineREG_JNI(name) { name, # name }
# endif
structRegJNIRec{
int(*mProc)(JNIEnv*);
constchar* mName;
};
constRegJNIRec gRegJNI[] = {
REG_JNI(register_android_os_Parcel),REG_JNI(register_android_opengl_jni_EGL14),REG_JNI(register_android_opengl_jni_EGL15),REG_JNI(register_android_opengl_jni_EGLExt),REG_JNI(register_android_os_MessageQueue)
};
最后,在AndroidRuntime::startReg
函数中,我们遍历这个数组并调用每个注册函数:
// frameworks/base/core/jni/AndroidRuntime.cpp
voidAndroidRuntime::startReg(JNIEnv* env){
ATRACE_NAME("RegisterAndroidNatives");
// ...
env->PushLocalFrame(200);
if(register_jni_procs(gRegJNI,NELEM(gRegJNI), env) <0) {
env->PopLocalFrame(NULL);
return-1;
}
env->PopLocalFrame(NULL);
// ...
}
通过深入分析Android Framework与JNI的代码,我们可以看到它们之间的神秘联系。从JNI的动态注册机制到调用链的探秘,每一个细节都体现了Android框架的精妙设计。希望本文能帮助开发者更好地理解Android Framework与JNI的工作原理,并在实际开发中更好地应用它们。
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
Copyright 2005-2024 yuanmayuan.com 【源码园】 版权所有 备案信息
声明: 本站非腾讯QQ官方网站 所有软件和文章来自互联网 如有异议 请与本站联系 本站为非赢利性网站 不接受任何赞助和广告