src/share/native/java/lang/ClassLoader.c

Print this page




  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <stdlib.h>
  27 #include <assert.h>
  28 
  29 #include "jni.h"
  30 #include "jni_util.h"
  31 #include "jlong.h"
  32 #include "jvm.h"
  33 #include "java_lang_ClassLoader.h"
  34 #include "java_lang_ClassLoader_NativeLibrary.h"

  35 
  36 /* defined in libverify.so/verify.dll (src file common/check_format.c) */
  37 extern jboolean VerifyClassname(char *utf_name, jboolean arrayAllowed);
  38 extern jboolean VerifyFixClassname(char *utf_name);
  39 
  40 static JNINativeMethod methods[] = {
  41     {"retrieveDirectives",  "()Ljava/lang/AssertionStatusDirectives;", (void *)&JVM_AssertionStatusDirectives}
  42 };
  43 
  44 JNIEXPORT void JNICALL
  45 Java_java_lang_ClassLoader_registerNatives(JNIEnv *env, jclass cls)
  46 {
  47     (*env)->RegisterNatives(env, cls, methods,
  48                             sizeof(methods)/sizeof(JNINativeMethod));
  49 }
  50 
  51 /* Convert java string to UTF char*. Use local buffer if possible,
  52    otherwise malloc new memory. Returns null IFF malloc failed. */
  53 static char*
  54 getUTF(JNIEnv *env, jstring str, char* localBuf, int bufSize)


 269     if (clname != buf) {
 270         free(clname);
 271     }
 272 
 273     return cls;
 274 }
 275 
 276 JNIEXPORT jclass JNICALL
 277 Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader,
 278                                            jstring name)
 279 {
 280     if (name == NULL) {
 281         return 0;
 282     } else {
 283         return JVM_FindLoadedClass(env, loader, name);
 284     }
 285 }
 286 
 287 static jfieldID handleID;
 288 static jfieldID jniVersionID;


 289 
 290 static jboolean initIDs(JNIEnv *env)
 291 {
 292     if (handleID == 0) {
 293         jclass this =
 294             (*env)->FindClass(env, "java/lang/ClassLoader$NativeLibrary");
 295         if (this == 0)
 296             return JNI_FALSE;
 297         handleID = (*env)->GetFieldID(env, this, "handle", "J");
 298         if (handleID == 0)
 299             return JNI_FALSE;
 300         jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I");
 301         if (jniVersionID == 0)
 302             return JNI_FALSE;




 303     }
 304     return JNI_TRUE;
 305 }
 306 
 307 typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *);
 308 typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *);
 309 
 310 /*


















































 311  * Class:     java_lang_ClassLoader_NativeLibrary
 312  * Method:    load
 313  * Signature: (Ljava/lang/String;)J
 314  */
 315 JNIEXPORT void JNICALL
 316 Java_java_lang_ClassLoader_00024NativeLibrary_load
 317   (JNIEnv *env, jobject this, jstring name)
 318 {
 319     const char *cname;
 320     jint jniVersion;
 321     jthrowable cause;
 322     void * handle;
 323 
 324     if (!initIDs(env))
 325         return;
 326 
 327     cname = JNU_GetStringPlatformChars(env, name, 0);
 328     if (cname == 0)
 329         return;
 330     handle = JVM_LoadLibrary(cname);
 331     if (handle) {
 332         const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
 333         JNI_OnLoad_t JNI_OnLoad;
 334         unsigned int i;
 335         for (i = 0; i < sizeof(onLoadSymbols) / sizeof(char *); i++) {
 336             JNI_OnLoad = (JNI_OnLoad_t)
 337                 JVM_FindLibraryEntry(handle, onLoadSymbols[i]);
 338             if (JNI_OnLoad) {
 339                 break;
 340             }
 341         }
 342         if (JNI_OnLoad) {
 343             JavaVM *jvm;
 344             (*env)->GetJavaVM(env, &jvm);
 345             jniVersion = (*JNI_OnLoad)(jvm, NULL);
 346         } else {
 347             jniVersion = 0x00010001;
 348         }
 349 
 350         cause = (*env)->ExceptionOccurred(env);
 351         if (cause) {
 352             (*env)->ExceptionClear(env);
 353             (*env)->Throw(env, cause);
 354             JVM_UnloadLibrary(handle);
 355             goto done;
 356         }
 357 
 358         if (!JVM_IsSupportedJNIVersion(jniVersion)) {

 359             char msg[256];
 360             jio_snprintf(msg, sizeof(msg),
 361                          "unsupported JNI version 0x%08X required by %s",
 362                          jniVersion, cname);
 363             JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg);
 364             JVM_UnloadLibrary(handle);
 365             goto done;
 366         }
 367         (*env)->SetIntField(env, this, jniVersionID, jniVersion);
 368     } else {
 369         cause = (*env)->ExceptionOccurred(env);
 370         if (cause) {
 371             (*env)->ExceptionClear(env);
 372             (*env)->SetLongField(env, this, handleID, (jlong)0);
 373             (*env)->Throw(env, cause);
 374         }
 375         goto done;
 376     }
 377     (*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle));

 378 
 379  done:
 380     JNU_ReleaseStringPlatformChars(env, name, cname);
 381 }
 382 
 383 /*
 384  * Class:     java_lang_ClassLoader_NativeLibrary
 385  * Method:    unload
 386  * Signature: ()V
 387  */
 388 JNIEXPORT void JNICALL
 389 Java_java_lang_ClassLoader_00024NativeLibrary_unload
 390   (JNIEnv *env, jobject this)
 391 {
 392     const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;
 393     void *handle;
 394     JNI_OnUnload_t JNI_OnUnload;
 395     unsigned int i;
 396 
 397     if (!initIDs(env))
 398         return;
 399 
 400     handle = jlong_to_ptr((*env)->GetLongField(env, this, handleID));
 401     for (i = 0; i < sizeof(onUnloadSymbols) / sizeof(char *); i++) {
 402         JNI_OnUnload = (JNI_OnUnload_t )
 403             JVM_FindLibraryEntry(handle, onUnloadSymbols[i]);
 404         if (JNI_OnUnload) {
 405             break;
 406         }
 407     }
 408 



 409     if (JNI_OnUnload) {
 410         JavaVM *jvm;
 411         (*env)->GetJavaVM(env, &jvm);
 412         (*JNI_OnUnload)(jvm, NULL);
 413     }
 414     JVM_UnloadLibrary(handle);

 415 }
 416 
 417 /*
 418  * Class:     java_lang_ClassLoader_NativeLibrary
 419  * Method:    find
 420  * Signature: (Ljava/lang/String;J)J
 421  */
 422 JNIEXPORT jlong JNICALL
 423 Java_java_lang_ClassLoader_00024NativeLibrary_find
 424   (JNIEnv *env, jobject this, jstring name)
 425 {
 426     jlong handle;
 427     const char *cname;
 428     jlong res;
 429 
 430     if (!initIDs(env))
 431         return jlong_zero;
 432 
 433     handle = (*env)->GetLongField(env, this, handleID);
 434     cname = (*env)->GetStringUTFChars(env, name, 0);
 435     if (cname == 0)
 436         return jlong_zero;
 437     res = ptr_to_jlong(JVM_FindLibraryEntry(jlong_to_ptr(handle), cname));
 438     (*env)->ReleaseStringUTFChars(env, name, cname);
 439     return res;
 440 }
 441 
 442 JNIEXPORT jobject JNICALL
 443 Java_java_lang_ClassLoader_getCaller(JNIEnv *env, jclass cls, jint index)
 444 {
 445     jobjectArray jcallerStack;
 446     int len;
 447 
 448     jcallerStack = JVM_GetClassContext(env);
 449     if ((*env)->ExceptionCheck(env)) {
 450         return NULL;
 451     }
 452     len = (*env)->GetArrayLength(env, jcallerStack);
 453     if (index < len) {
 454         return (*env)->GetObjectArrayElement(env, jcallerStack, index);
 455     }
 456     return NULL;
 457 }
 458 




























































  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <stdlib.h>
  27 #include <assert.h>
  28 
  29 #include "jni.h"
  30 #include "jni_util.h"
  31 #include "jlong.h"
  32 #include "jvm.h"
  33 #include "java_lang_ClassLoader.h"
  34 #include "java_lang_ClassLoader_NativeLibrary.h"
  35 #include <string.h>
  36 
  37 /* defined in libverify.so/verify.dll (src file common/check_format.c) */
  38 extern jboolean VerifyClassname(char *utf_name, jboolean arrayAllowed);
  39 extern jboolean VerifyFixClassname(char *utf_name);
  40 
  41 static JNINativeMethod methods[] = {
  42     {"retrieveDirectives",  "()Ljava/lang/AssertionStatusDirectives;", (void *)&JVM_AssertionStatusDirectives}
  43 };
  44 
  45 JNIEXPORT void JNICALL
  46 Java_java_lang_ClassLoader_registerNatives(JNIEnv *env, jclass cls)
  47 {
  48     (*env)->RegisterNatives(env, cls, methods,
  49                             sizeof(methods)/sizeof(JNINativeMethod));
  50 }
  51 
  52 /* Convert java string to UTF char*. Use local buffer if possible,
  53    otherwise malloc new memory. Returns null IFF malloc failed. */
  54 static char*
  55 getUTF(JNIEnv *env, jstring str, char* localBuf, int bufSize)


 270     if (clname != buf) {
 271         free(clname);
 272     }
 273 
 274     return cls;
 275 }
 276 
 277 JNIEXPORT jclass JNICALL
 278 Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader,
 279                                            jstring name)
 280 {
 281     if (name == NULL) {
 282         return 0;
 283     } else {
 284         return JVM_FindLoadedClass(env, loader, name);
 285     }
 286 }
 287 
 288 static jfieldID handleID;
 289 static jfieldID jniVersionID;
 290 static jfieldID loadedID;
 291 static void *procHandle;
 292 
 293 static jboolean initIDs(JNIEnv *env)
 294 {
 295     if (handleID == 0) {
 296         jclass this =
 297             (*env)->FindClass(env, "java/lang/ClassLoader$NativeLibrary");
 298         if (this == 0)
 299             return JNI_FALSE;
 300         handleID = (*env)->GetFieldID(env, this, "handle", "J");
 301         if (handleID == 0)
 302             return JNI_FALSE;
 303         jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I");
 304         if (jniVersionID == 0)
 305             return JNI_FALSE;
 306         loadedID = (*env)->GetFieldID(env, this, "loaded", "Z");
 307         if (loadedID == 0)
 308              return JNI_FALSE;
 309         procHandle = getProcessHandle();
 310     }
 311     return JNI_TRUE;
 312 }
 313 
 314 typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *);
 315 typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *);
 316 
 317 /*
 318  * Support for builtin library. JNI_On(Un)Load_<lib_name> if it exists.
 319  * If cname == NULL then just find normal JNI_On(Un)Load entry point
 320  */
 321 static void *findBuiltinJniFunction(JNIEnv *env, void *handle,
 322                                     const char *cname, jboolean isLoad) {
 323     const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
 324     const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;
 325     const char **syms;
 326     int symsLen;
 327     void *entryName = NULL;
 328     char *jniEntryName;
 329     int i;
 330     int len;
 331 
 332     // Check for JNI_On(Un)Load<_libname> function
 333     if (isLoad) {
 334         syms = onLoadSymbols;
 335         symsLen = sizeof(onLoadSymbols) / sizeof(char *);
 336     } else {
 337         syms = onUnloadSymbols;
 338         symsLen = sizeof(onUnloadSymbols) / sizeof(char *);
 339     }
 340     for (i = 0; i < symsLen; i++) {
 341         // cname + sym + '_' + '\0'
 342         if ((len = (cname != NULL ? strlen(cname) : 0) + strlen(syms[i]) + 2) >
 343             FILENAME_MAX) {
 344             goto done;
 345         }
 346         jniEntryName = malloc(len);
 347         if (jniEntryName == NULL) {
 348             JNU_ThrowOutOfMemoryError(env, NULL);
 349             goto done;
 350         }
 351         strcpy(jniEntryName, syms[i]);
 352         if (cname != NULL) {
 353             strcat(jniEntryName, "_");
 354             strcat(jniEntryName, cname);
 355         }
 356         entryName = JVM_FindLibraryEntry(handle, jniEntryName);
 357         free(jniEntryName);
 358         if(entryName) {
 359             break;
 360         }
 361     }
 362 
 363  done:
 364     return entryName;
 365 }
 366 
 367 /*
 368  * Class:     java_lang_ClassLoader_NativeLibrary
 369  * Method:    load
 370  * Signature: (Ljava/lang/String;Z)V
 371  */
 372 JNIEXPORT void JNICALL
 373 Java_java_lang_ClassLoader_00024NativeLibrary_load
 374   (JNIEnv *env, jobject this, jstring name, jboolean isBuiltin)
 375 {
 376     const char *cname;
 377     jint jniVersion;
 378     jthrowable cause;
 379     void * handle;
 380 
 381     if (!initIDs(env))
 382         return;
 383 
 384     cname = JNU_GetStringPlatformChars(env, name, 0);
 385     if (cname == 0)
 386         return;
 387     handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname);
 388     if (handle) {
 389         const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
 390         JNI_OnLoad_t JNI_OnLoad;
 391         JNI_OnLoad = (JNI_OnLoad_t)findBuiltinJniFunction(env, handle,
 392                                                isBuiltin ? cname : NULL,
 393                                                JNI_TRUE);





 394         if (JNI_OnLoad) {
 395             JavaVM *jvm;
 396             (*env)->GetJavaVM(env, &jvm);
 397             jniVersion = (*JNI_OnLoad)(jvm, NULL);
 398         } else {
 399             jniVersion = 0x00010001;
 400         }
 401 
 402         cause = (*env)->ExceptionOccurred(env);
 403         if (cause) {
 404             (*env)->ExceptionClear(env);
 405             (*env)->Throw(env, cause);
 406             JVM_UnloadLibrary(handle);
 407             goto done;
 408         }
 409 
 410         if (!JVM_IsSupportedJNIVersion(jniVersion) ||
 411             (isBuiltin && jniVersion < JNI_VERSION_1_8)) {
 412             char msg[256];
 413             jio_snprintf(msg, sizeof(msg),
 414                          "unsupported JNI version 0x%08X required by %s",
 415                          jniVersion, cname);
 416             JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg);
 417             JVM_UnloadLibrary(handle);
 418             goto done;
 419         }
 420         (*env)->SetIntField(env, this, jniVersionID, jniVersion);
 421     } else {
 422         cause = (*env)->ExceptionOccurred(env);
 423         if (cause) {
 424             (*env)->ExceptionClear(env);
 425             (*env)->SetLongField(env, this, handleID, (jlong)0);
 426             (*env)->Throw(env, cause);
 427         }
 428         goto done;
 429     }
 430     (*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle));
 431     (*env)->SetBooleanField(env, this, loadedID, JNI_TRUE);
 432 
 433  done:
 434     JNU_ReleaseStringPlatformChars(env, name, cname);
 435 }
 436 
 437 /*
 438  * Class:     java_lang_ClassLoader_NativeLibrary
 439  * Method:    unload
 440  * Signature: (Z)V
 441  */
 442 JNIEXPORT void JNICALL
 443 Java_java_lang_ClassLoader_00024NativeLibrary_unload
 444 (JNIEnv *env, jobject this, jstring name, jboolean isBuiltin)
 445 {
 446     const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;
 447     void *handle;
 448     JNI_OnUnload_t JNI_OnUnload;
 449      const char *cname;
 450 
 451     if (!initIDs(env))
 452         return;
 453     cname = JNU_GetStringPlatformChars(env, name, 0);
 454     if (cname == NULL) {
 455         return;





 456     }
 457     handle = jlong_to_ptr((*env)->GetLongField(env, this, handleID));
 458     JNI_OnUnload = (JNI_OnUnload_t )findBuiltinJniFunction(env, handle,
 459                                                 isBuiltin ? cname : NULL,
 460                                                 JNI_FALSE);
 461     if (JNI_OnUnload) {
 462         JavaVM *jvm;
 463         (*env)->GetJavaVM(env, &jvm);
 464         (*JNI_OnUnload)(jvm, NULL);
 465     }
 466     JVM_UnloadLibrary(handle);
 467     JNU_ReleaseStringPlatformChars(env, name, cname);
 468 }
 469 
 470 /*
 471  * Class:     java_lang_ClassLoader_NativeLibrary
 472  * Method:    find
 473  * Signature: (Ljava/lang/String;)J
 474  */
 475 JNIEXPORT jlong JNICALL
 476 Java_java_lang_ClassLoader_00024NativeLibrary_find
 477   (JNIEnv *env, jobject this, jstring name)
 478 {
 479     jlong handle;
 480     const char *cname;
 481     jlong res;
 482 
 483     if (!initIDs(env))
 484         return jlong_zero;
 485 
 486     handle = (*env)->GetLongField(env, this, handleID);
 487     cname = (*env)->GetStringUTFChars(env, name, 0);
 488     if (cname == 0)
 489         return jlong_zero;
 490     res = ptr_to_jlong(JVM_FindLibraryEntry(jlong_to_ptr(handle), cname));
 491     (*env)->ReleaseStringUTFChars(env, name, cname);
 492     return res;
 493 }
 494 
 495 JNIEXPORT jobject JNICALL
 496 Java_java_lang_ClassLoader_getCaller(JNIEnv *env, jclass cls, jint index)
 497 {
 498     jobjectArray jcallerStack;
 499     int len;
 500 
 501     jcallerStack = JVM_GetClassContext(env);
 502     if ((*env)->ExceptionCheck(env)) {
 503         return NULL;
 504     }
 505     len = (*env)->GetArrayLength(env, jcallerStack);
 506     if (index < len) {
 507         return (*env)->GetObjectArrayElement(env, jcallerStack, index);
 508     }
 509     return NULL;
 510 }
 511 
 512 /*
 513  * Class:     java_lang_ClassLoader_NativeLibrary
 514  * Method:    findBuiltinLib
 515  * Signature: (Ljava/lang/String;)Ljava/lang/String;
 516  */
 517 JNIEXPORT jstring JNICALL
 518 Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib
 519   (JNIEnv *env, jclass cls, jstring name)
 520 {
 521     const char *cname;
 522     char *libName;
 523     int prefixLen = (int) strlen(JNI_LIB_PREFIX);
 524     int suffixLen = (int) strlen(JNI_LIB_SUFFIX);
 525     int len;
 526     jstring lib;
 527     void *ret;
 528     const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
 529 
 530     if (name == NULL) {
 531         JNU_ThrowInternalError(env, "NULL filename for native library");
 532         return NULL;
 533     }
 534     // Can't call initIDs because it will recurse into NativeLibrary via
 535     // FindClass to check context so set prochandle here as well.
 536     procHandle = getProcessHandle();
 537     cname = JNU_GetStringPlatformChars(env, name, 0);
 538     if (cname == NULL) {
 539         return NULL;
 540     }
 541     // Copy name Skipping PREFIX
 542     len = strlen(cname);
 543     if (len <= (prefixLen+suffixLen)) {
 544         JNU_ReleaseStringPlatformChars(env, name, cname);
 545         return NULL;
 546     }
 547     libName = malloc(len + 1); //+1 for null if prefix+suffix == 0
 548     if (libName == NULL) {
 549         JNU_ThrowOutOfMemoryError(env, NULL);
 550         return NULL;
 551     }
 552     if (len > prefixLen) {
 553         strcpy(libName, cname+prefixLen);
 554     }
 555     JNU_ReleaseStringPlatformChars(env, name, cname);
 556 
 557     // Strip SUFFIX
 558     libName[strlen(libName)-suffixLen] = '\0';
 559 
 560     // Check for JNI_OnLoad_libname function
 561     ret = findBuiltinJniFunction(env, procHandle, libName, JNI_TRUE);
 562     if (ret != NULL) {
 563         lib = JNU_NewStringPlatform(env, libName);
 564         free(libName);
 565         return lib;
 566     }
 567     free(libName);
 568     return NULL;
 569 }