@chopsticks
2014-12-22T01:44:12.000000Z
字数 3965
阅读 2500
Android
JNI is the way java code adopted to use native code. Usually, native code exists as a shared library. Thus, Java code should load this kinds of shared library first before using those exported fucntions.
Java provide two API for native shared library loading:
Note: It seems that, these two apis are almost same, acturally they have different totally different arument.
- the argumentlibName
means the native shared library name which was difined in makefile under JNI compile environment. E.g, if developer defined the lib name as "test", then the complied native shared library name should belibtest.so
, and developer can use api like that:System.loadlibrary("test")
, or "System.load("libtest.so")".
- In another words, libName "XXX" forSystem.loadLibrary
refers to a lib namedlibXXX.so
, and os will automatically search liblibXXX.so
in some specifical directories; However, the argument libpathName forSystem.load
refers to a lib which named same with the argument, even can include the fully path.
No matter which way the developer adopts, the last step in Java code is calling a native method named nativeLoad
.
The native method nativeLoad
is mapped to Dalvik_java_lang_Runtime_nativeLoad
, a function in libdvm.so, existing as native code, defined in java_lang_Runtime.c
.
Location:``
JNI_OnLoad
jniRegisterNativeMethods
Location:dalvik/vm/native.c
/*
* We add one of these to the hash table for every library we load. The
* hash is on the "pathName" field.
*/
struct SharedLib {
char* pathName; /* absolute path to library */
void* handle; /* from dlopen */
Object* classLoader; /* ClassLoader we are associated with */
pthread_mutex_t onLoadLock; /* guards remaining items */
pthread_cond_t onLoadCond; /* wait for JNI_OnLoad in other thread */
u4 onLoadThreadId; /* recursive invocation guard */
OnLoadState onLoadResult; /* result of earlier JNI_OnLoad */
};
dvmHashTableLookup
is a key function for manipulating SharedLibs
in a process. Usually, it works by coordinating with several other callback functions. Usage:
/*
* (This is a dvmHashTableLookup callback.)
*
* Find an entry that matches the string.
*/
static int hashcmpNameStr(const void* ventry, const void* vname)
{
const SharedLib* pLib = (const SharedLib*) ventry;
const char* name = (const char*) vname;
return strcmp(pLib->pathName, name);
}
/*
* (This is a dvmHashTableLookup callback.)
*
* Find an entry that matches the new entry.
*
* We don't compare the class loader here, because you're not allowed to
* have the same shared library associated with more than one CL.
*/
static int hashcmpSharedLib(const void* ventry, const void* vnewEntry)
{
const SharedLib* pLib = (const SharedLib*) ventry;
const SharedLib* pNewLib = (const SharedLib*) vnewEntry;
ALOGD("--- comparing %p '%s' %p '%s'",
pLib, pLib->pathName, pNewLib, pNewLib->pathName);
return strcmp(pLib->pathName, pNewLib->pathName);
}
/*
* Check to see if an entry with the same pathname already exists.
*/
static SharedLib* findSharedLibEntry(const char* pathName)
{
u4 hash = dvmComputeUtf8Hash(pathName);
void* ent;
ent = dvmHashTableLookup(gDvm.nativeLibs, hash, (void*)pathName,
hashcmpNameStr, false);
return (SharedLib*)ent;
}
/*
* Add the new entry to the table.
*
* Returns the table entry, which will not be the same as "pLib" if the
* entry already exists.
*/
static SharedLib* addSharedLibEntry(SharedLib* pLib)
{
u4 hash = dvmComputeUtf8Hash(pLib->pathName);
/*
* Do the lookup with the "add" flag set. If we add it, we will get
* our own pointer back. If somebody beat us to the punch, we'll get
* their pointer back instead.
*/
return (SharedLib*)dvmHashTableLookup(gDvm.nativeLibs, hash, pLib,
hashcmpSharedLib, true);
}
/*
* Free up an entry. (This is a dvmHashTableFree callback.)
*/
static void freeSharedLibEntry(void* ptr)
{
SharedLib* pLib = (SharedLib*) ptr;
/*
* Calling dlclose() here is somewhat dangerous, because it's possible
* that a thread outside the VM is still accessing the code we loaded.
*/
if (false)
dlclose(pLib->handle);
free(pLib->pathName);
free(pLib);
}
更多关于dvmHashTableLookp的使用可参考这里。