Quelle méthode appelle finalement JNI_OnLoad

J’essayais de comprendre comment JNI_OnLoad est appelé en interne. J’ai fini par comprendre le tutoriel ci-dessous, mais il ne jette aucune lumière sur la partie de code qui appelle réellement JNI_OnLoad en tant qu’appel de fonction interne. Aidez-moi à trouver cette fonction de lien qui appelle explicitement JNI_OnLoad. J’ai observé que System.loadLibrary appelle Runtime, qui à nouveau appelle Classloader. Mais toujours impossible de trouver le lien natif.

J’ai été particulièrement intéressé par celui de 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 : Ma trace de fichier basée sur la réponse de @Code Painters est la suivante:

  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 Ssortingng nativeLoad(Ssortingng 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); } 

Je comprends maintenant que Runtime.loadlibrary est surchargé avec la fonction native Dalvik_java_lang_Runtime_nativeLoad et que Classloader.loadlibrary n’est pas évoqué. S’il vous plait corrigez moi si je me trompe.

Pour Android, vous devriez regarder dans dalvik / vm / Native.c , qui définit l’interface JNI.

La fonction la plus pertinente est celle-ci:

 bool dvmLoadNativeCode(const char* pathName, Object* classLoader); 

C’est l’endroit où la bibliothèque est dlopen() . Et la partie la plus intéressante de celle-ci:

  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; 

Comme vous pouvez le constater, JNI_OnLoad est simplement résolu à l’aide de dlsym() et appelé à l’aide du pointeur renvoyé. Le rest de cette partie de code vérifie la valeur renvoyée par JNI_OnLoad , rien de vraiment excitant.

Je pense que cela devrait être à peu près le même pour les autres machines virtuelles – donc grep pour dlopen() et dlsym() – après tout, il s’agit simplement de charger une bibliothèque partagée et de résoudre les symboles.

Éditer: En parlant du fichier exact que vous avez mentionné, Android.mk dans le même répertoire comstack et lie ce fichier dans la bibliothèque partagée libandroid_servers . La recherche de ce nom de bibliothèque révèle les services / java / com / android / server / SystemServer.java .

Ce qui est pertinent:

 public static void main(Ssortingng[] args) { // ... System.loadLibrary("android_servers"); // ... } 

Ainsi, le chargement de la bibliothèque (et donc un appel à JNI_OnLoad() dans onload.cpp ) est effectué dans le contexte du démarrage du service système d’Android. Si vous souhaitez en savoir plus sur le chargement du service système, à quel moment / à quel moment, je vous recommande cette présentation .