Reputation: 1471
I was trying to figure out how JNI_OnLoad is called internally. I eventually figured out the below tutorial but it does not throw any light on what code part actually calls JNI_OnLoad as an internal function call. Please help me with finding that link function which explicitly calls JNI_OnLoad. i observed that System.loadLibrary calls Runtime which again calls Classloader. But still could not find the native link.
I was especially interested with the one in OnLoad.cpp (android/platform_frameworks_base/blob/master/services/jni/onload.cpp)
JNI_OnLoad
jint JNI_OnLoad(JavaVM *vm, void *reserved);
The VM calls JNI_OnLoad when the native library is loaded (for example, through
System.loadLibrary). JNI_OnLoad must return the JNI version needed by the native library.
In order to use any of the new JNI functions, a native library must export a JNI_OnLoad function that returns JNI_VERSION_1_2. If the native library does not export a JNI_OnLoad function, the VM assumes that the library only requires JNI version JNI_VERSION_1_1. If the VM does not recognize the version number returned by JNI_OnLoad, the native library cannot be loaded.
Edit: My file trace based on response of @Code Painters is below:
System.loadLibrary("android_servers");
|
|The call System.loadLibrary(name) is effectively equivalent
| to the call
|
V
Runtime.getRuntime().loadLibrary(name)
|
|public static Runtime getRuntime() {
| return currentRuntime;}
|
| // Here, also,Classloader.loadlibrary is called,
| but this is over-ridden (?)
| by the Native function of Runtime.java below
V
/dalvik/vm/native/java_lang_Runtime.cpp (The jni native
implementation of Runtime.java):
/*
* static String nativeLoad(String filename, ClassLoader loader)
*
* Load the specified full path as a dynamic library filled with
* JNI-compatible methods. Returns null on success, or a failure
* message on failure.
*/
static void Dalvik_java_lang_Runtime_nativeLoad{
//
success = dvmLoadNativeCode(fileName, classLoader, &reason);
}
I now understand Runtime.loadlibrary is overloaded with the Dalvik_java_lang_Runtime_nativeLoad native function and Classloader.loadlibrary is not evoked. Please correct me if I am wrong.
Upvotes: 19
Views: 34343
Reputation: 7275
For Android, you should look into dalvik/vm/Native.c, which defines the JNI interface.
The most relevant function is this one:
bool dvmLoadNativeCode(const char* pathName, Object* classLoader);
This the place, where the library is dlopen()
-ed. And the most interesting part of it:
vonLoad = dlsym(handle, "JNI_OnLoad");
if (vonLoad == NULL) {
LOGD("No JNI_OnLoad found in %s %p\n", pathName, classLoader);
} else {
/*
* Call JNI_OnLoad. We have to override the current class
* loader, which will always be "null" since the stuff at the
* top of the stack is around Runtime.loadLibrary(). (See
* the comments in the JNI FindClass function.)
*/
OnLoadFunc func = vonLoad;
Object* prevOverride = self->classLoaderOverride;
self->classLoaderOverride = classLoader;
oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
LOGV("+++ calling JNI_OnLoad(%s)\n", pathName);
version = (*func)(gDvm.vmList, NULL);
dvmChangeStatus(self, oldStatus);
self->classLoaderOverride = prevOverride;
As you can see, JNI_OnLoad
is simply resolved using dlsym()
and called using the returned pointer. The rest of this code part is checking the value returned by JNI_OnLoad
, nothing really exciting.
I believe it should look pretty much the same for other VMs - so just grep for dlopen()
and dlsym()
- after all it's just plain shared library loading and symbol resolution.
Edit: Speaking of the exact file you mention, Android.mk
in the same directory compiles and links this file into libandroid_servers
shared library. Grepping around for this library name reveals services/java/com/android/server/SystemServer.java.
What's relevant:
public static void main(String[] args) {
// ...
System.loadLibrary("android_servers");
// ...
}
So, the loading of library (and thus a call to JNI_OnLoad()
in onload.cpp
) is performed in the context of Android's system service startup. If you want to know more about how/when the system service loads, I recommend this presentation.
Upvotes: 28