干货|JNI实现机制
//……
};
//挪用当地要领会到这里来寻找系统当地方
DalvikNativeFunc dvmLookupInternalNativeMethod(const Method* method)
{
const char* classDescriptor = method->clazz->descriptor;
const DalvikNativeClass* pClass;
u4 hash;
hash = dvmComputeUtf8Hash(classDescriptor);
pClass = gDvmNativeMethodSet;//遍历全局当地要领荟萃,寻找注册的系统当地要领
while (true) {
if (pClass->classDescriptor == NULL)
break;
if (pClass->classDescriptorHash == hash &&
strcmp(pClass->classDescriptor, classDescriptor) == 0)
{
const DalvikNativeMethod* pMeth = pClass->methodInfo;
while (true) {
if (pMeth->name == NULL)
break;
if (dvmCompareNameDescriptorAndMethod(pMeth->name,
pMeth->signature, method) == 0)
{
/* match */
return pMeth->fnPtr;
}
pMeth++;
}
}
pClass++;
}
return NULL;
}
注书籍地要领
/dalvik/vm/Jni.cpp
RegisterNatives()-> dvmRegisterJNIMethod()-> dvmUseJniBridge() -> Class.dvmSetNativeFunc()
static jint RegisterNatives(JNIEnv* env, jclass jclazz, const JNINativeMethod* methods, jint nMethods)
{
//......
for (int i = 0; i < nMethods; i++) {
if (!dvmRegisterJNIMethod(clazz, methods[i].name,
methods[i].signature, methods[i].fnPtr))
{
return JNI_ERR;
}
}
return JNI_OK;
}
static bool dvmRegisterJNIMethod(ClassObject* clazz, const char* methodName,
const char* signature, void* fnPtr)
{
//......
if (method->nativeFunc != dvmResolveNativeMethod) {
/* this is allowed, but unusual */
ALOGV("Note: %s.%s:%s was already registered", clazz->descriptor, methodName, signature);
}
method->fastJni = fastJni;
dvmUseJNIBridge(method, fnPtr);
ALOGV("JNI-registered %s.%s:%s", clazz->descriptor, methodName, signature);
return true;
}
void dvmUseJNIBridge(Method* method, void* func) {
//……
DalvikBridgeFunc bridge = gDvmJni.useCheckJni ? dvmCheckCallJNIMethod : dvmCallJNIMethod;
dvmSetNativeFunc(method, bridge, (const u2*) func);//将nativeFunc指向dvmCallJNIMethod,并将insns指向func
}
void dvmCallJNIMethod(const u4* args, JValue* pResult, const Method* method, Thread* self) {
//......
JNIEnv* env = self->jniEnv;
COMPUTE_STACK_SUM(self);
dvmPlatformInvoke(env, (ClassObject*) staticMethodClass,
method->jniArgInfo, method->insSize, modArgs, method->shorty,
(void*) method->insns, pResult);//挪用要领insns,对于差别的cpu架构会有差别的挪用方式
//......
}
/dalvik/vm/oo/Class.cpp
dvmSetNativeFunc()
void dvmSetNativeFunc(Method* method, DalvikBridgeFunc func, const u2* insns)
{
//......
//将nativeFunc指向dvmCallJNIMethod,并将insns指向func
if (insns != NULL) {
/* update both, ensuring that "insns" is observed first */
method->insns = insns;
android_atomic_release_store((int32_t) func,
(volatile int32_t*)(void*) &method->nativeFunc);
} else {
/* only update nativeFunc */
method->nativeFunc = func;
}
//......
}
至此,我们可以知道挪用JNI要领最终会通过 Jni.dvmCallJNIMethod() -> dvmPlatformInvoke() 来凭据差别cpu架构实现举行挪用。
Class被加载的历程
Android中ClassLoader都是继续自BaseDexClassLoader,加载dex是通过BaseDexClassLoader来加载的,会将dex中的信息都生存到DexPathList中,后面加载类的历程如下:
BaseDexClassLoader.findClass() -> DexPathList.findClass() -> 遍历dexElements -> DexFile.loadClassBinaryName() -> DexFile.defineClass() -> DexFile.defineClassNative()
/dalvik/vm/native/dalvik_system_DexFile.cpp
defineClassNative()-> Class.dvmDefineClass()
const DalvikNativeMethod dvm_dalvik_system_DexFile[] = {
//……
{ "defineClassNative", "(Ljava/lang/String;Ljava/lang/ClassLoader;I)Ljava/lang/Class;",
Dalvik_dalvik_system_DexFile_defineClassNative },
{ "getClassNameList", "(I)[Ljava/lang/String;",
Dalvik_dalvik_system_DexFile_getClassNameList },
//……
};
static void Dalvik_dalvik_system_DexFile_defineClassNative(const u4* args,
JValue* pResult)
{
//......
clazz = dvmDefineClass(pDvmDex, descriptor, loader);
Thread* self = dvmThreadSelf();
//......
}
/dalvik/vm/oo/Class.cpp
dvmDefineClass() -> findClassNoInit() -> dvmLookupClass()
-> loadClassFromDex() -> loadClassFromDex0() -> loadMethodFromDex() -> dvmResolveNativeMethod()
ClassObject* dvmDefineClass(DvmDex* pDvmDex, const char* descriptor,
Object* classLoader)
“沈阳软件公司”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与
我们联系删除或处理,客服QQ:55506560,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同
其观点或证实其内容的真实性。
热门文章
使用“扫一扫”即可将网页分享至朋友圈。