In the blog Java JNI (a) virtual machine ClassLoader Jnilibrary discussed in Java Library is classloader to load, then we see how classloader to load of a library.
Classloader.c
[CPP]
Jniexportvoidjnicall java_java_lang_classloader_00024nativelibrary_load (jnienv*env, Jobject This, jstring name) { Const Char*CNAME; Jint jniversion; Jthrowable cause; void*handle; if(!Initids (env))return; CNAME= Jnu_getstringplatformchars (env, name,0); if(CNAME = =0) return; Handle=jvm_loadlibrary (CNAME); if(handle) {Const Char*onloadsymbols[] =Jni_onload_symbols; jni_onload_t Jni_onload; inti; for(i =0; I <sizeof(Onloadsymbols)/sizeof(Char*); i++) {Jni_onload=(jni_onload_t) jvm_findlibraryentry (handle, onloadsymbols[i]); if(jni_onload) { Break; } } if(jni_onload) {JAVAVM*JVM; (*ENV)->GETJAVAVM (env, &JVM); Jniversion= (*jni_onload) (JVM, NULL); } Else{jniversion=0x00010001; } cause= (*env)exceptionoccurred (env); if(Cause) {(*ENV)Exceptionclear (env); (*ENV)Throw (env, cause); Jvm_unloadlibrary (handle); GotoDone ; } if(!jvm_issupportedjniversion (jniversion)) { Charmsg[ the]; jio_snprintf (MSG,sizeof(msg),"Unsupported JNI version 0x%08X required by%s", jniversion, CNAME); Jnu_throwbyname (env,"Java/lang/unsatisfiedlinkerror", MSG); Jvm_unloadlibrary (handle); GotoDone ; } (*ENV)->setintfield (env, This, Jniversionid, jniversion); } Else{cause= (*env)exceptionoccurred (env); if(Cause) {(*ENV)Exceptionclear (env); (*ENV)->setlongfield (env, This, Handleid, (Jlong) NULL); (*ENV)Throw (env, cause); } GotoDone ; } (*ENV)->setlongfield (env, This, Handleid, Ptr_to_jlong (handle)); Done:jnu_releasestringplatformchars (env, name, CNAME); }
1. Jvm_loadlibrary
The kernel function of the load library in the JVM is very simple to implement, and the system function Dlopen is used to open the library file in Linux, which can be referenced in detail.
[CPP]
void * OS::d ll_load (constcharcharint ebuflen)
2. Jvm_findlibraryentry
When the JVM loads the library file, it tries to find the address of the Jni_onload method in the library, and in Linux calls the Dlsym function to get the address of the method through the previous Dlopen loading the library's pointer. While Dlsym is non-thread-safe in glibc2.0, it requires lock protection, although loading libraries in Java already has lock protection, but only fine-grained locks on the same ClassLoader object.
[CPP]
void* OS::d ll_lookup (voidconstChar* name) { Pthread_mutex_lock ( &Dl_mutex); void* res = Dlsym (handle, name); Pthread_mutex_unlock (&Dl_mutex); return res; }
3. Method Jni_onload
The JVM provides a way to allow you to do something you want to do when loading a library file, which is the Jni_onload method
As mentioned in 2, when loading a dynamic-link library, the JVM will try to find the Jni_onload method, and it will call the function, so that you can do some initialization things in the function, such as the Register native method.
[CPP]
void* reserved) {}
The Jni_onload returns a version of JNI, supported in the case of version 1.6:
[CPP]
Jboolean threads::is_supported_jni_version (jint version) { ifreturn jni_true; ifreturn jni_true; if return jni_true; return jni_false; }
The complete loading process is
First load the dynamic link library, try to find the Jni_onload method, and run the method, for us to implement the initialization method that can be customized.
Java JNI Implementation principle (ii) How to load jnilibrary under Linux