干货|JNI实现机制
{
assert(pDvmDex != NULL);
return findClassNoInit(descriptor, classLoader, pDvmDex);
}
static ClassObject* findClassNoInit(const char* descriptor, Object* loader,
DvmDex* pDvmDex)
{
Thread* self = dvmThreadSelf();
ClassObject* clazz;
//......
clazz = dvmLookupClass(descriptor, loader, true);//从gDvm全局变量的loadedClasses中找
if (clazz == NULL) {
clazz = loadClassFromDex(pDvmDex, pClassDef, loader);//没找到,则从dex中找
}
//......
return clazz;
}
static ClassObject* loadClassFromDex(DvmDex* pDvmDex, const DexClassDef* pClassDef, Object* classLoader)
{
ClassObject* result;
//......
result = loadClassFromDex0(pDvmDex, pClassDef, &header, pEncodedData,
classLoader);
//......
return result;
}
static ClassObject* loadClassFromDex0(DvmDex* pDvmDex,
const DexClassDef* pClassDef, const DexClassDataHeader* pHeader,
const u1* pEncodedData, Object* classLoader)
{
ClassObject* newClass = NULL;
//......
loadIFieldFromDex(newClass, &field, &newClass->ifields[i]);//遍历加载成员变量
//......
loadMethodFromDex(newClass, &method, &newClass->directMethods[i]);//遍历加载要领
//......
newClass->sourceFile = dexGetSourceFile(pDexFile, pClassDef);
return newClass;
}
static void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod, Method* meth)
{
//......
if (dvmIsNativeMethod(meth)) {//若是是当地要领,会将nativeFunc指向dvmResolveNativeMethod,当执行当地要领时就会执行dvmResolveNativeMethod要领
meth->nativeFunc = dvmResolveNativeMethod;
meth->jniArgInfo = computeJniArgInfo(&meth->prototype);
}
//......
}
上面跟踪下来我们知道每个dex中的当地要领都市执行到 dvmResolveNativeMethod(),我们来看看该要领做了哪些事情?
/dalvik/vm/Native.cpp
dvmResolveNativeMethod() -> InternalNative.dvmLookupInternalNativeMethod()
dvmResolveNativeMethod() -> lookupSharedLibMethod() -> findMethodInLib()
void dvmResolveNativeMethod(const u4* args, JValue* pResult,
const Method* method, Thread* self)
{
//……
/* start with our internal-native methods */
DalvikNativeFunc infunc = dvmLookupInternalNativeMethod(method);//寻找系统内部当地要领
if (infunc != NULL) {
//……
DalvikBridgeFunc dfunc = (DalvikBridgeFunc) infunc;
dvmSetNativeFunc((Method*) method, dfunc, NULL);
dfunc(args, pResult, method, self);//执行
return;
}
/* now scan any DLLs we have loaded for JNI signatures */
void* func = lookupSharedLibMethod(method);//在动态加载的so中寻找当地要领
if (func != NULL) {
/* found it, point it at the JNI bridge and then call it */
dvmUseJNIBridge((Method*) method, func);
(*method->nativeFunc)(args, pResult, method, self);//执行nativeFunc
return;
}
//……
dvmThrowUnsatisfiedLinkError("Native method not found", method);//没找到当地要领,则会报UnsatisfiedLinkError
}
static void* lookupSharedLibMethod(const Method* method)
{
if (gDvm.nativeLibs == NULL) {
ALOGE("Unexpected init state: nativeLibs not ready");
dvmAbort();
}
return (void*) dvmHashForeach(gDvm.nativeLibs, findMethodInLib,
(void*) method);//先从gDvm全局变量nativeLibs中寻找,没找到,则通过findMethodInLib在so中寻找,找到则生存到nativeLibs中
}
static int findMethodInLib(void* vlib, void* vmethod)
{
const SharedLib* pLib = (const SharedLib*) vlib;
const Method* meth = (const Method*) vmethod;
//......
/*
* First, we try it without the signature.
*/
preMangleCM =
createJniNameString(meth->clazz->descriptor, meth->name, &len);
if (preMangleCM == NULL)
goto bail;
mangleCM = mangleString(preMangleCM, len);
if (mangleCM == NULL)
goto bail;
//通过createJniNameString和mangleString,获得最终函数的名称路径Java_package_methodName
ALOGV("+++ calling dlsym(%s)", mangleCM);
func = dlsym(pLib->handle, mangleCM);//凭据动态链接库操作句柄与符号,返回符号对应的地址
//......
return (int) func;
}
系统内部当地要领通过 dvmLookupInternalNativeMethod()要领来寻找详细实现的
通过System.loadLibrary加载的当地要领,则是通过 lookupSharedLibMethod()要领来寻找的
(要领名称花样:Java_package_methodName)
/dalvik/vm/native/InternalNative.cpp
dvmLookupInternalNativeMethod() -> java_lang_runtime.Dalvik_java_lang_Runtime_nativeLoad()
DalvikNativeFunc dvmLookupInternalNativeMethod(const Method* method)
“沈阳软件公司”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与
我们联系删除或处理,客服QQ:55506560,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同
其观点或证实其内容的真实性。
热门文章
使用“扫一扫”即可将网页分享至朋友圈。