Dalvik虚拟机JNI方法的注册过程分析 (五)

2014-11-24 10:58:08 · 作者: · 浏览: 3
g_Runtime_nativeLoad(const u4* args,
JValue* pResult)
{
StringObject* fileNameObj = (StringObject*) args[0];
Object* classLoader = (Object*) args[1];
char* fileName = NULL;
StringObject* result = NULL;
char* reason = NULL;
bool success;

assert(fileNameObj != NULL);
fileName = dvmCreateCstrFromString(fileNameObj);

success = dvmLoadNativeCode(fileName, classLoader, &reason);
if (!success) {
const char* msg = (reason != NULL) reason : "unknown failure";
result = dvmCreateStringFromCstr(msg);
dvmReleaseTrackedAlloc((Object*) result, NULL);
}

free(reason);
free(fileName);
RETURN_PTR(result);
}

static void Dalvik_java_lang_Runtime_nativeLoad(const u4* args,
JValue* pResult)
{
StringObject* fileNameObj = (StringObject*) args[0];
Object* classLoader = (Object*) args[1];
char* fileName = NULL;
StringObject* result = NULL;
char* reason = NULL;
bool success;

assert(fileNameObj != NULL);
fileName = dvmCreateCstrFromString(fileNameObj);

success = dvmLoadNativeCode(fileName, classLoader, &reason);
if (!success) {
const char* msg = (reason != NULL) reason : "unknown failure";
result = dvmCreateStringFromCstr(msg);
dvmReleaseTrackedAlloc((Object*) result, NULL);
}

free(reason);
free(fileName);
RETURN_PTR(result);
} 这个函数定义在文件dalvik/vm/native/java_lang_Runtime.c中。

参数args[0]保存的是一个Java层的String对象,这个String对象描述的就是要加载的so文件,函数Dalvik_java_lang_Runtime_nativeLoad首先是调有函数dvmCreateCstrFromString来将它转换成一个C++层的字符串fileName,然后再调用函数dvmLoadNativeCode来执行加载so文件的操作。

接下来,我们就继续分函数dvmLoadNativeCode的实现,以便可以了解一个so文件的加载过程。

Step 4. dvmLoadNativeCode


[cpp] bool dvmLoadNativeCode(const char* pathName, Object* classLoader,
char** detail)
{
SharedLib* pEntry;
void* handle;
......

pEntry = findSharedLibEntry(pathName);
if (pEntry != NULL) {
if (pEntry->classLoader != classLoader) {
......
return false;
}
......

if (!checkOnLoadResult(pEntry))
return false;
return true;
}
......

handle = dlopen(pathName, RTLD_LAZY);
......

/* create a new entry */
SharedLib* pNewEntry;
pNewEntry = (SharedLib*) calloc(1, sizeof(SharedLib));
pNewEntry->pathName = strdup(pathName);
pNewEntry->handle = handle;
pNewEntry->classLoader = classLoader;
......

/* try to add it to the list */
SharedLib* pActualEntry = addSharedLibEntry(pNewEntry);

if (pNewEntry != pActualEntry) {
......
freeSharedLibEntry(pNewEntry);
return checkOnLoadResult(pActualEntry);
} else {
......

bool result = true;
void* vonLoad;
int version;

vonLoad = dlsym(handle, "JNI_OnLoad");
if (vonLoad == NULL) {
LOGD("No JNI_OnLoad found in %s %p, skipping init\n",
pathName, classLoader);
} else {
......

OnLoadFunc func = vonLoad;
......

version = (*func)(gDvm.vmList, NULL);
......

if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 &&
version != JNI_VERSION_1_6)