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 // cname + sym + '_' + '\0'
342 if ((len = (cname != NULL ? strlen(cname) : 0) + strlen(syms[i]) + 2) >
343 FILENAME_MAX) {
344 goto done;
345 }
346 jniFunctionName = malloc(len);
347 if (jniFunctionName == NULL) {
348 JNU_ThrowOutOfMemoryError(env, NULL);
349 goto done;
350 }
351 buildJniFunctionName(syms[i], cname, jniFunctionName);
352 entryName = JVM_FindLibraryEntry(handle, jniFunctionName);
353 free(jniFunctionName);
354 if(entryName) {
355 break;
356 }
357 }
358
359 done:
360 return entryName;
361 }
362
363 /*
364 * Class: java_lang_ClassLoader_NativeLibrary
365 * Method: load
366 * Signature: (Ljava/lang/String;Z)V
367 */
368 JNIEXPORT void JNICALL
369 Java_java_lang_ClassLoader_00024NativeLibrary_load
370 (JNIEnv *env, jobject this, jstring name, jboolean isBuiltin)
371 {
372 const char *cname;
373 jint jniVersion;
374 jthrowable cause;
375 void * handle;
376
377 if (!initIDs(env))
378 return;
379
380 cname = JNU_GetStringPlatformChars(env, name, 0);
381 if (cname == 0)
382 return;
383 handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname);
384 if (handle) {
385 JNI_OnLoad_t JNI_OnLoad;
386 JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle,
387 isBuiltin ? cname : NULL,
388 JNI_TRUE);
389 if (JNI_OnLoad) {
390 JavaVM *jvm;
391 (*env)->GetJavaVM(env, &jvm);
392 jniVersion = (*JNI_OnLoad)(jvm, NULL);
393 } else {
394 jniVersion = 0x00010001;
395 }
396
397 cause = (*env)->ExceptionOccurred(env);
398 if (cause) {
399 (*env)->ExceptionClear(env);
400 (*env)->Throw(env, cause);
401 JVM_UnloadLibrary(handle);
402 goto done;
403 }
404
405 if (!JVM_IsSupportedJNIVersion(jniVersion) ||
406 (isBuiltin && jniVersion < JNI_VERSION_1_8)) {
407 char msg[256];
408 jio_snprintf(msg, sizeof(msg),
409 "unsupported JNI version 0x%08X required by %s",
410 jniVersion, cname);
411 JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg);
412 JVM_UnloadLibrary(handle);
413 goto done;
414 }
415 (*env)->SetIntField(env, this, jniVersionID, jniVersion);
416 } else {
417 cause = (*env)->ExceptionOccurred(env);
418 if (cause) {
419 (*env)->ExceptionClear(env);
420 (*env)->SetLongField(env, this, handleID, (jlong)0);
421 (*env)->Throw(env, cause);
422 }
423 goto done;
424 }
425 (*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle));
426 (*env)->SetBooleanField(env, this, loadedID, JNI_TRUE);
427
428 done:
429 JNU_ReleaseStringPlatformChars(env, name, cname);
430 }
431
432 /*
433 * Class: java_lang_ClassLoader_NativeLibrary
434 * Method: unload
435 * Signature: (Z)V
436 */
437 JNIEXPORT void JNICALL
438 Java_java_lang_ClassLoader_00024NativeLibrary_unload
439 (JNIEnv *env, jobject this, jstring name, jboolean isBuiltin)
440 {
441 const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;
442 void *handle;
443 JNI_OnUnload_t JNI_OnUnload;
444 const char *cname;
445
446 if (!initIDs(env))
447 return;
448 cname = JNU_GetStringPlatformChars(env, name, 0);
449 if (cname == NULL) {
450 return;
451 }
452 handle = jlong_to_ptr((*env)->GetLongField(env, this, handleID));
453 JNI_OnUnload = (JNI_OnUnload_t )findJniFunction(env, handle,
454 isBuiltin ? cname : NULL,
455 JNI_FALSE);
456 if (JNI_OnUnload) {
457 JavaVM *jvm;
458 (*env)->GetJavaVM(env, &jvm);
459 (*JNI_OnUnload)(jvm, NULL);
460 }
461 JVM_UnloadLibrary(handle);
462 JNU_ReleaseStringPlatformChars(env, name, cname);
463 }
464
465 /*
466 * Class: java_lang_ClassLoader_NativeLibrary
467 * Method: find
468 * Signature: (Ljava/lang/String;)J
469 */
470 JNIEXPORT jlong JNICALL
471 Java_java_lang_ClassLoader_00024NativeLibrary_find
472 (JNIEnv *env, jobject this, jstring name)
473 {
474 jlong handle;
475 const char *cname;
476 jlong res;
477
478 if (!initIDs(env))
479 return jlong_zero;
480
481 handle = (*env)->GetLongField(env, this, handleID);
482 cname = (*env)->GetStringUTFChars(env, name, 0);
483 if (cname == 0)
484 return jlong_zero;
485 res = ptr_to_jlong(JVM_FindLibraryEntry(jlong_to_ptr(handle), cname));
486 (*env)->ReleaseStringUTFChars(env, name, cname);
487 return res;
488 }
489
490 JNIEXPORT jobject JNICALL
491 Java_java_lang_ClassLoader_getCaller(JNIEnv *env, jclass cls, jint index)
492 {
493 jobjectArray jcallerStack;
494 int len;
495
496 jcallerStack = JVM_GetClassContext(env);
497 if ((*env)->ExceptionCheck(env)) {
498 return NULL;
499 }
500 len = (*env)->GetArrayLength(env, jcallerStack);
501 if (index < len) {
502 return (*env)->GetObjectArrayElement(env, jcallerStack, index);
503 }
504 return NULL;
505 }
506
507 /*
508 * Class: java_lang_ClassLoader_NativeLibrary
509 * Method: findBuiltinLib
510 * Signature: (Ljava/lang/String;)Ljava/lang/String;
511 */
512 JNIEXPORT jstring JNICALL
513 Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib
514 (JNIEnv *env, jclass cls, jstring name)
515 {
516 const char *cname;
517 char *libName;
518 int prefixLen = (int) strlen(JNI_LIB_PREFIX);
519 int suffixLen = (int) strlen(JNI_LIB_SUFFIX);
520 int len;
521 jstring lib;
522 void *ret;
523 const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
524
525 if (name == NULL) {
526 JNU_ThrowInternalError(env, "NULL filename for native library");
527 return NULL;
528 }
529 // Can't call initIDs because it will recurse into NativeLibrary via
530 // FindClass to check context so set prochandle here as well.
531 procHandle = getProcessHandle();
532 cname = JNU_GetStringPlatformChars(env, name, 0);
533 if (cname == NULL) {
534 JNU_ThrowOutOfMemoryError(env, NULL);
535 return NULL;
536 }
537 // Copy name Skipping PREFIX
538 len = strlen(cname);
539 if (len <= (prefixLen+suffixLen)) {
540 JNU_ReleaseStringPlatformChars(env, name, cname);
541 return NULL;
542 }
543 libName = malloc(len + 1); //+1 for null if prefix+suffix == 0
544 if (libName == NULL) {
545 JNU_ReleaseStringPlatformChars(env, name, cname);
546 JNU_ThrowOutOfMemoryError(env, NULL);
547 return NULL;
548 }
549 if (len > prefixLen) {
550 strcpy(libName, cname+prefixLen);
551 }
552 JNU_ReleaseStringPlatformChars(env, name, cname);
553
554 // Strip SUFFIX
555 libName[strlen(libName)-suffixLen] = '\0';
556
557 // Check for JNI_OnLoad_libname function
558 ret = findJniFunction(env, procHandle, libName, JNI_TRUE);
559 if (ret != NULL) {
560 lib = JNU_NewStringPlatform(env, libName);
561 free(libName);
562 return lib;
563 }
564 free(libName);
565 return NULL;
566 }
|