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

Print this page


   1 /*
   2  * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  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 




























































   1 /*
   2  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  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 finding 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 *findJniFunction(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 *jniFunctionName;
 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         jniFunctionName = buildJniFunctionName(env, syms[i], cname);
 342         if (jniFunctionName == NULL) {
 343             // exception thrown
 344             goto done;
 345         }
 346         entryName = JVM_FindLibraryEntry(handle, jniFunctionName);
 347         free(jniFunctionName);
 348         if(entryName) {
 349             break;
 350         }
 351     }
 352 
 353  done:
 354     return entryName;
 355 }
 356 
 357 /*
 358  * Class:     java_lang_ClassLoader_NativeLibrary
 359  * Method:    load
 360  * Signature: (Ljava/lang/String;Z)V
 361  */
 362 JNIEXPORT void JNICALL
 363 Java_java_lang_ClassLoader_00024NativeLibrary_load
 364   (JNIEnv *env, jobject this, jstring name, jboolean isBuiltin)
 365 {
 366     const char *cname;
 367     jint jniVersion;
 368     jthrowable cause;
 369     void * handle;
 370 
 371     if (!initIDs(env))
 372         return;
 373 
 374     cname = JNU_GetStringPlatformChars(env, name, 0);
 375     if (cname == 0)
 376         return;
 377     handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname);
 378     if (handle) {

 379         JNI_OnLoad_t JNI_OnLoad;
 380         JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle,
 381                                                isBuiltin ? cname : NULL,
 382                                                JNI_TRUE);





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





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