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

干货|JNI实现机制

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

{

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

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

推荐阅读