加载中 ...
首页 > 常见问题 正文

干货|JNI实现机制

2019-03-24 10:31:08 来源:沈阳软件公司 作者:沈阳软件开发

//……

};

 

//挪用当地要领会到这里来寻找系统当地方

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,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同

其观点或证实其内容的真实性。

推荐阅读