1 /* 2 * Copyright (c) 1996, 2015, 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 "check_classname.h" 34 #include "java_lang_ClassLoader.h" 35 #include "java_lang_ClassLoader_NativeLibrary.h" 36 #include <string.h> 37 38 static JNINativeMethod methods[] = { 39 {"retrieveDirectives", "()Ljava/lang/AssertionStatusDirectives;", (void *)&JVM_AssertionStatusDirectives} 40 }; 41 42 JNIEXPORT void JNICALL 43 Java_java_lang_ClassLoader_registerNatives(JNIEnv *env, jclass cls) 44 { 45 (*env)->RegisterNatives(env, cls, methods, 46 sizeof(methods)/sizeof(JNINativeMethod)); 47 } 48 49 /* Convert java string to UTF char*. Use local buffer if possible, 50 otherwise malloc new memory. Returns null IFF malloc failed. */ 51 static char* 52 getUTF(JNIEnv *env, jstring str, char* localBuf, int bufSize) 53 { 54 char* utfStr = NULL; 55 56 int len = (*env)->GetStringUTFLength(env, str); 57 int unicode_len = (*env)->GetStringLength(env, str); 58 if (len >= bufSize) { 59 utfStr = malloc(len + 1); 60 if (utfStr == NULL) { 61 JNU_ThrowOutOfMemoryError(env, NULL); 62 return NULL; 63 } 64 } else { 65 utfStr = localBuf; 66 } 67 (*env)->GetStringUTFRegion(env, str, 0, unicode_len, utfStr); 68 69 return utfStr; 70 } 71 72 JNIEXPORT jclass JNICALL 73 Java_java_lang_ClassLoader_defineClass1(JNIEnv *env, 74 jclass cls, 75 jobject loader, 76 jstring name, 77 jbyteArray data, 78 jint offset, 79 jint length, 80 jobject pd, 81 jstring source) 82 { 83 jbyte *body; 84 char *utfName; 85 jclass result = 0; 86 char buf[128]; 87 char* utfSource; 88 char sourceBuf[1024]; 89 90 if (data == NULL) { 91 JNU_ThrowNullPointerException(env, 0); 92 return 0; 93 } 94 95 /* Work around 4153825. malloc crashes on Solaris when passed a 96 * negative size. 97 */ 98 if (length < 0) { 99 JNU_ThrowArrayIndexOutOfBoundsException(env, 0); 100 return 0; 101 } 102 103 body = (jbyte *)malloc(length); 104 105 if (body == 0) { 106 JNU_ThrowOutOfMemoryError(env, 0); 107 return 0; 108 } 109 110 (*env)->GetByteArrayRegion(env, data, offset, length, body); 111 112 if ((*env)->ExceptionOccurred(env)) 113 goto free_body; 114 115 if (name != NULL) { 116 utfName = getUTF(env, name, buf, sizeof(buf)); 117 if (utfName == NULL) { 118 goto free_body; 119 } 120 fixClassname(utfName); 121 } else { 122 utfName = NULL; 123 } 124 125 if (source != NULL) { 126 utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf)); 127 if (utfSource == NULL) { 128 goto free_utfName; 129 } 130 } else { 131 utfSource = NULL; 132 } 133 result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource); 134 135 if (utfSource && utfSource != sourceBuf) 136 free(utfSource); 137 138 free_utfName: 139 if (utfName && utfName != buf) 140 free(utfName); 141 142 free_body: 143 free(body); 144 return result; 145 } 146 147 JNIEXPORT jclass JNICALL 148 Java_java_lang_ClassLoader_defineClass2(JNIEnv *env, 149 jclass cls, 150 jobject loader, 151 jstring name, 152 jobject data, 153 jint offset, 154 jint length, 155 jobject pd, 156 jstring source) 157 { 158 jbyte *body; 159 char *utfName; 160 jclass result = 0; 161 char buf[128]; 162 char* utfSource; 163 char sourceBuf[1024]; 164 165 assert(data != NULL); // caller fails if data is null. 166 assert(length >= 0); // caller passes ByteBuffer.remaining() for length, so never neg. 167 // caller passes ByteBuffer.position() for offset, and capacity() >= position() + remaining() 168 assert((*env)->GetDirectBufferCapacity(env, data) >= (offset + length)); 169 170 body = (*env)->GetDirectBufferAddress(env, data); 171 172 if (body == 0) { 173 JNU_ThrowNullPointerException(env, 0); 174 return 0; 175 } 176 177 body += offset; 178 179 if (name != NULL) { 180 utfName = getUTF(env, name, buf, sizeof(buf)); 181 if (utfName == NULL) { 182 JNU_ThrowOutOfMemoryError(env, NULL); 183 return result; 184 } 185 fixClassname(utfName); 186 } else { 187 utfName = NULL; 188 } 189 190 if (source != NULL) { 191 utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf)); 192 if (utfSource == NULL) { 193 JNU_ThrowOutOfMemoryError(env, NULL); 194 goto free_utfName; 195 } 196 } else { 197 utfSource = NULL; 198 } 199 result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource); 200 201 if (utfSource && utfSource != sourceBuf) 202 free(utfSource); 203 204 free_utfName: 205 if (utfName && utfName != buf) 206 free(utfName); 207 208 return result; 209 } 210 211 JNIEXPORT jclass JNICALL 212 Java_java_lang_ClassLoader_defineClass0(JNIEnv *env, 213 jclass cls, 214 jobject loader, 215 jclass lookup, 216 jstring name, 217 jbyteArray data, 218 jint offset, 219 jint length, 220 jobject pd, 221 jboolean initialize, 222 jint flags, 223 jobject classData) 224 { 225 jbyte *body; 226 char *utfName; 227 jclass result = 0; 228 char buf[128]; 229 230 if (data == NULL) { 231 JNU_ThrowNullPointerException(env, 0); 232 return 0; 233 } 234 235 /* Work around 4153825. malloc crashes on Solaris when passed a 236 * negative size. 237 */ 238 if (length < 0) { 239 JNU_ThrowArrayIndexOutOfBoundsException(env, 0); 240 return 0; 241 } 242 243 body = (jbyte *)malloc(length); 244 if (body == 0) { 245 JNU_ThrowOutOfMemoryError(env, 0); 246 return 0; 247 } 248 249 (*env)->GetByteArrayRegion(env, data, offset, length, body); 250 251 if ((*env)->ExceptionOccurred(env)) 252 goto free_body; 253 254 if (name != NULL) { 255 utfName = getUTF(env, name, buf, sizeof(buf)); 256 if (utfName == NULL) { 257 goto free_body; 258 } 259 fixClassname(utfName); 260 } else { 261 utfName = NULL; 262 } 263 264 return JVM_LookupDefineClass(env, lookup, utfName, loader, body, length, pd, initialize, flags, classData); 265 266 free_body: 267 free(body); 268 return result; 269 } 270 271 /* 272 * Returns NULL if class not found. 273 */ 274 JNIEXPORT jclass JNICALL 275 Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader, 276 jstring classname) 277 { 278 char *clname; 279 jclass cls = 0; 280 char buf[128]; 281 282 if (classname == NULL) { 283 return 0; 284 } 285 286 clname = getUTF(env, classname, buf, sizeof(buf)); 287 if (clname == NULL) { 288 JNU_ThrowOutOfMemoryError(env, NULL); 289 return NULL; 290 } 291 fixClassname(clname); 292 293 if (!verifyClassname(clname, JNI_TRUE)) { /* expects slashed name */ 294 goto done; 295 } 296 297 cls = JVM_FindClassFromBootLoader(env, clname); 298 299 done: 300 if (clname != buf) { 301 free(clname); 302 } 303 304 return cls; 305 } 306 307 JNIEXPORT jclass JNICALL 308 Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader, 309 jstring name) 310 { 311 if (name == NULL) { 312 return 0; 313 } else { 314 return JVM_FindLoadedClass(env, loader, name); 315 } 316 } 317 318 static jfieldID handleID; 319 static jfieldID jniVersionID; 320 static void *procHandle; 321 322 static jboolean initIDs(JNIEnv *env) 323 { 324 if (handleID == 0) { 325 jclass this = 326 (*env)->FindClass(env, "java/lang/ClassLoader$NativeLibrary"); 327 if (this == 0) 328 return JNI_FALSE; 329 handleID = (*env)->GetFieldID(env, this, "handle", "J"); 330 if (handleID == 0) 331 return JNI_FALSE; 332 jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I"); 333 if (jniVersionID == 0) 334 return JNI_FALSE; 335 procHandle = getProcessHandle(); 336 } 337 return JNI_TRUE; 338 } 339 340 typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *); 341 typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *); 342 343 /* 344 * Support for finding JNI_On(Un)Load_<lib_name> if it exists. 345 * If cname == NULL then just find normal JNI_On(Un)Load entry point 346 */ 347 static void *findJniFunction(JNIEnv *env, void *handle, 348 const char *cname, jboolean isLoad) { 349 const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS; 350 const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS; 351 const char **syms; 352 int symsLen; 353 void *entryName = NULL; 354 char *jniFunctionName; 355 int i; 356 size_t len; 357 358 // Check for JNI_On(Un)Load<_libname> function 359 if (isLoad) { 360 syms = onLoadSymbols; 361 symsLen = sizeof(onLoadSymbols) / sizeof(char *); 362 } else { 363 syms = onUnloadSymbols; 364 symsLen = sizeof(onUnloadSymbols) / sizeof(char *); 365 } 366 for (i = 0; i < symsLen; i++) { 367 // cname + sym + '_' + '\0' 368 if ((len = (cname != NULL ? strlen(cname) : 0) + strlen(syms[i]) + 2) > 369 FILENAME_MAX) { 370 goto done; 371 } 372 jniFunctionName = malloc(len); 373 if (jniFunctionName == NULL) { 374 JNU_ThrowOutOfMemoryError(env, NULL); 375 goto done; 376 } 377 buildJniFunctionName(syms[i], cname, jniFunctionName); 378 entryName = JVM_FindLibraryEntry(handle, jniFunctionName); 379 free(jniFunctionName); 380 if(entryName) { 381 break; 382 } 383 } 384 385 done: 386 return entryName; 387 } 388 389 /* 390 * Class: java_lang_ClassLoader_NativeLibrary 391 * Method: load0 392 * Signature: (Ljava/lang/String;Z)Z 393 */ 394 JNIEXPORT jboolean JNICALL 395 Java_java_lang_ClassLoader_00024NativeLibrary_load0 396 (JNIEnv *env, jobject this, jstring name, jboolean isBuiltin) 397 { 398 const char *cname; 399 jint jniVersion; 400 jthrowable cause; 401 void * handle; 402 jboolean loaded = JNI_FALSE; 403 404 if (!initIDs(env)) 405 return JNI_FALSE; 406 407 cname = JNU_GetStringPlatformChars(env, name, 0); 408 if (cname == 0) 409 return JNI_FALSE; 410 handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname); 411 if (handle) { 412 JNI_OnLoad_t JNI_OnLoad; 413 JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle, 414 isBuiltin ? cname : NULL, 415 JNI_TRUE); 416 if (JNI_OnLoad) { 417 JavaVM *jvm; 418 (*env)->GetJavaVM(env, &jvm); 419 jniVersion = (*JNI_OnLoad)(jvm, NULL); 420 } else { 421 jniVersion = 0x00010001; 422 } 423 424 cause = (*env)->ExceptionOccurred(env); 425 if (cause) { 426 (*env)->ExceptionClear(env); 427 (*env)->Throw(env, cause); 428 if (!isBuiltin) { 429 JVM_UnloadLibrary(handle); 430 } 431 goto done; 432 } 433 434 if (!JVM_IsSupportedJNIVersion(jniVersion) || 435 (isBuiltin && jniVersion < JNI_VERSION_1_8)) { 436 char msg[256]; 437 jio_snprintf(msg, sizeof(msg), 438 "unsupported JNI version 0x%08X required by %s", 439 jniVersion, cname); 440 JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg); 441 if (!isBuiltin) { 442 JVM_UnloadLibrary(handle); 443 } 444 goto done; 445 } 446 (*env)->SetIntField(env, this, jniVersionID, jniVersion); 447 } else { 448 cause = (*env)->ExceptionOccurred(env); 449 if (cause) { 450 (*env)->ExceptionClear(env); 451 (*env)->SetLongField(env, this, handleID, (jlong)0); 452 (*env)->Throw(env, cause); 453 } 454 goto done; 455 } 456 (*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle)); 457 loaded = JNI_TRUE; 458 459 done: 460 JNU_ReleaseStringPlatformChars(env, name, cname); 461 return loaded; 462 } 463 464 /* 465 * Class: java_lang_ClassLoader_NativeLibrary 466 * Method: unload 467 * Signature: (Ljava/lang/String;ZJ)V 468 */ 469 JNIEXPORT void JNICALL 470 Java_java_lang_ClassLoader_00024NativeLibrary_unload 471 (JNIEnv *env, jclass cls, jstring name, jboolean isBuiltin, jlong address) 472 { 473 const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS; 474 void *handle; 475 JNI_OnUnload_t JNI_OnUnload; 476 const char *cname; 477 478 if (!initIDs(env)) 479 return; 480 cname = JNU_GetStringPlatformChars(env, name, 0); 481 if (cname == NULL) { 482 return; 483 } 484 handle = jlong_to_ptr(address); 485 JNI_OnUnload = (JNI_OnUnload_t )findJniFunction(env, handle, 486 isBuiltin ? cname : NULL, 487 JNI_FALSE); 488 if (JNI_OnUnload) { 489 JavaVM *jvm; 490 (*env)->GetJavaVM(env, &jvm); 491 (*JNI_OnUnload)(jvm, NULL); 492 } 493 if (!isBuiltin) { 494 JVM_UnloadLibrary(handle); 495 } 496 JNU_ReleaseStringPlatformChars(env, name, cname); 497 } 498 499 /* 500 * Class: java_lang_ClassLoader_NativeLibrary 501 * Method: findEntry 502 * Signature: (Ljava/lang/String;)J 503 */ 504 JNIEXPORT jlong JNICALL 505 Java_java_lang_ClassLoader_00024NativeLibrary_findEntry 506 (JNIEnv *env, jobject this, jstring name) 507 { 508 jlong handle; 509 const char *cname; 510 jlong res; 511 512 if (!initIDs(env)) 513 return jlong_zero; 514 515 handle = (*env)->GetLongField(env, this, handleID); 516 cname = (*env)->GetStringUTFChars(env, name, 0); 517 if (cname == 0) 518 return jlong_zero; 519 res = ptr_to_jlong(JVM_FindLibraryEntry(jlong_to_ptr(handle), cname)); 520 (*env)->ReleaseStringUTFChars(env, name, cname); 521 return res; 522 } 523 /* 524 * Class: java_lang_ClassLoader 525 * Method: findBuiltinLib 526 * Signature: (Ljava/lang/String;)Ljava/lang/String; 527 */ 528 JNIEXPORT jstring JNICALL 529 Java_java_lang_ClassLoader_findBuiltinLib 530 (JNIEnv *env, jclass cls, jstring name) 531 { 532 const char *cname; 533 char *libName; 534 size_t prefixLen = strlen(JNI_LIB_PREFIX); 535 size_t suffixLen = strlen(JNI_LIB_SUFFIX); 536 size_t len; 537 jstring lib; 538 void *ret; 539 const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS; 540 541 if (name == NULL) { 542 JNU_ThrowInternalError(env, "NULL filename for native library"); 543 return NULL; 544 } 545 procHandle = getProcessHandle(); 546 cname = JNU_GetStringPlatformChars(env, name, 0); 547 if (cname == NULL) { 548 return NULL; 549 } 550 // Copy name Skipping PREFIX 551 len = strlen(cname); 552 if (len <= (prefixLen+suffixLen)) { 553 JNU_ReleaseStringPlatformChars(env, name, cname); 554 return NULL; 555 } 556 libName = malloc(len + 1); //+1 for null if prefix+suffix == 0 557 if (libName == NULL) { 558 JNU_ReleaseStringPlatformChars(env, name, cname); 559 JNU_ThrowOutOfMemoryError(env, NULL); 560 return NULL; 561 } 562 if (len > prefixLen) { 563 strcpy(libName, cname+prefixLen); 564 } 565 JNU_ReleaseStringPlatformChars(env, name, cname); 566 567 // Strip SUFFIX 568 libName[strlen(libName)-suffixLen] = '\0'; 569 570 // Check for JNI_OnLoad_libname function 571 ret = findJniFunction(env, procHandle, libName, JNI_TRUE); 572 if (ret != NULL) { 573 lib = JNU_NewStringPlatform(env, libName); 574 free(libName); 575 return lib; 576 } 577 free(libName); 578 return NULL; 579 }