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 }
|