libGetNamedModuleTest.c revision 12723:afedee84773e
1/* 2 * Copyright (c) 2016, 2017, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24#include <stdio.h> 25#include <string.h> 26#include "jvmti.h" 27 28#ifdef __cplusplus 29extern "C" { 30#endif 31 32#ifndef JNI_ENV_ARG 33 34#ifdef __cplusplus 35#define JNI_ENV_ARG(x, y) y 36#define JNI_ENV_PTR(x) x 37#else 38#define JNI_ENV_ARG(x,y) x, y 39#define JNI_ENV_PTR(x) (*x) 40#endif 41 42#endif 43 44#define TranslateError(err) "JVMTI error" 45 46#define PASSED 0 47#define FAILED 2 48 49static const char *EXC_CNAME = "java/lang/Exception"; 50static const char* MOD_CNAME = "Ljava/lang/Module;"; 51 52static jvmtiEnv *jvmti = NULL; 53static jint result = PASSED; 54static jboolean printdump = JNI_FALSE; 55 56static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved); 57 58JNIEXPORT 59jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { 60 return Agent_Initialize(jvm, options, reserved); 61} 62 63JNIEXPORT 64jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) { 65 return Agent_Initialize(jvm, options, reserved); 66} 67 68JNIEXPORT 69jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { 70 return JNI_VERSION_1_8; 71} 72 73static 74jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 75 jint res; 76 77 if (options != NULL && strcmp(options, "printdump") == 0) { 78 printdump = JNI_TRUE; 79 } 80 81 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), 82 JVMTI_VERSION_9); 83 if (res != JNI_OK || jvmti == NULL) { 84 printf(" Error: wrong result of a valid call to GetEnv!\n"); 85 return JNI_ERR; 86 } 87 88 return JNI_OK; 89} 90 91static 92jint throw_exc(JNIEnv *env, char *msg) { 93 jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME)); 94 95 if (exc_class == NULL) { 96 printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME); 97 return -1; 98 } 99 return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg); 100} 101 102static 103jobject get_class_loader(jclass cls) { 104 jvmtiError err = JVMTI_ERROR_NONE; 105 jobject loader = NULL; 106 107 if (printdump == JNI_TRUE) { 108 printf(">>> getting class loader ...\n"); 109 } 110 err = (*jvmti)->GetClassLoader(jvmti, cls, &loader); 111 if (err != JVMTI_ERROR_NONE) { 112 printf(" Error in GetClassLoader: %s (%d)\n", TranslateError(err), err); 113 } 114 return loader; 115} 116 117static 118jclass jlM(JNIEnv *env) { 119 jclass cls = NULL; 120 121 cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, MOD_CNAME)); 122 if (cls == NULL) { 123 printf(" Error in JNI FindClass: %s\n", MOD_CNAME); 124 } 125 return cls; 126} 127 128jmethodID 129get_method(JNIEnv *env, jclass clazz, const char * name, const char *sig) { 130 jmethodID method = NULL; 131 132 method = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, clazz), name, sig); 133 if (method == NULL) { 134 printf(" Error in JNI GetMethodID %s with signature %s", name, sig); 135 } 136 return method; 137} 138 139static 140jobject get_module_loader(JNIEnv *env, jobject module) { 141 static jmethodID cl_method = NULL; 142 jobject loader = NULL; 143 144 if (cl_method == NULL) { 145 cl_method = get_method(env, jlM(env), "getClassLoader", "()Ljava/lang/ClassLoader;"); 146 } 147 loader = (jobject)JNI_ENV_PTR(env)->CallObjectMethod(JNI_ENV_ARG(env, module), cl_method); 148 return loader; 149} 150 151static 152const char* get_module_name(JNIEnv *env, jobject module) { 153 static jmethodID method = NULL; 154 jobject loader = NULL; 155 jstring jstr = NULL; 156 const char *name = NULL; 157 const char *nstr = NULL; 158 159 if (method == NULL) { 160 method = get_method(env, jlM(env), "getName", "()Ljava/lang/String;"); 161 } 162 jstr = (jstring)JNI_ENV_PTR(env)->CallObjectMethod(JNI_ENV_ARG(env, module), method); 163 if (jstr != NULL) { 164 name = JNI_ENV_PTR(env)->GetStringUTFChars(JNI_ENV_ARG(env, jstr), NULL); 165 } 166 loader = get_module_loader(env, module); 167 nstr = (name == NULL) ? "<UNNAMED>" : name; 168 printf(" loader: %p, module: %p, name: %s\n", loader, module, nstr); 169 return name; 170} 171 172static 173jvmtiError get_module(JNIEnv *env, 174 jobject loader, 175 const char* pkg_name, 176 jobject* module_ptr, 177 const char** mod_name_ptr) { 178 jvmtiError err = JVMTI_ERROR_NONE; 179 const char* name = (pkg_name == NULL) ? "<NULL>" : pkg_name; 180 181 printf(">>> getting module by loader %p and package \"%s\"\n", loader, name); 182 *mod_name_ptr = NULL; 183 err = (*jvmti)->GetNamedModule(jvmti, loader, pkg_name, module_ptr); 184 if (err != JVMTI_ERROR_NONE) { 185 printf(" Error in GetNamedModule for package \"%s\": %s (%d)\n", 186 name, TranslateError(err), err); 187 return err; 188 } 189 printf(" returned module: %p\n", *module_ptr); 190 if (*module_ptr == NULL) { // named module was not found 191 return err; 192 } 193 *mod_name_ptr = get_module_name(env, *module_ptr); 194 return err; 195} 196 197static 198jint get_all_modules(JNIEnv *env) { 199 jvmtiError err; 200 jint cnt = -1; 201 jint idx = 0; 202 jobject* modules; 203 204 printf(">>> Inspecting modules with GetAllModules\n"); 205 err = (*jvmti)->GetAllModules(jvmti, &cnt, &modules); 206 if (err != JVMTI_ERROR_NONE) { 207 printf("Error in GetAllModules: %d\n", err); 208 return -1; 209 } 210 for (idx = 0; idx < cnt; ++idx) { 211 get_module_name(env, modules[idx]); 212 } 213 return cnt; 214} 215 216static 217jint check_bad_loader(JNIEnv *env, jobject loader) { 218 jvmtiError err = JVMTI_ERROR_NONE; 219 jobject module = NULL; 220 const char* mod_name = NULL; 221 222 err = get_module(env, loader, "", &module, &mod_name); 223 if (err != JVMTI_ERROR_ILLEGAL_ARGUMENT) { 224 return FAILED; 225 } 226 printf(" got expected JVMTI_ERROR_ILLEGAL_ARGUMENT for bad loader\n"); 227 return PASSED; 228} 229 230static 231jint check_system_loader(JNIEnv *env, jobject loader) { 232 jvmtiError err = JVMTI_ERROR_NONE; 233 jobject module = NULL; 234 const char* exp_name = NULL; 235 const char* mod_name = NULL; 236 237 // NULL pointer for package name 238 err = get_module(env, loader, NULL, &module, &mod_name); 239 if (err != JVMTI_ERROR_NULL_POINTER) { 240 throw_exc(env, "check #SN1: failed to return JVMTI_ERROR_NULL_POINTER for NULL package"); 241 return FAILED; 242 } 243 244 // NULL pointer for module_ptr 245 err = (*jvmti)->GetNamedModule(jvmti, loader, "", NULL); 246 if (err != JVMTI_ERROR_NULL_POINTER) { 247 throw_exc(env, "check #SN2: failed to return JVMTI_ERROR_NULL_POINTER for NULL module_ptr"); 248 return FAILED; 249 } 250 251 // Unnamed/default package "" 252 err = get_module(env, loader, "", &module, &mod_name); 253 if (err != JVMTI_ERROR_NONE) { 254 throw_exc(env, "check #S1: failed to return JVMTI_ERROR_NONE for default package"); 255 return FAILED; 256 } 257 if (module != NULL || mod_name != NULL) { 258 throw_exc(env, "check #S2: failed to return NULL-module for default package"); 259 return FAILED; 260 } 261 262 // Test package: MyPackage 263 err = get_module(env, loader, "MyPackage", &module, &mod_name); 264 if (err != JVMTI_ERROR_NONE) { 265 throw_exc(env, "check #S3: failed to return JVMTI_ERROR_NONE for MyPackage"); 266 return FAILED; 267 } 268 if (module != NULL || mod_name != NULL) { 269 throw_exc(env, "check #S4: failed to return NULL-module for MyPackage"); 270 return FAILED; 271 } 272 273 // Package: com/sun/jdi 274 exp_name = "jdk.jdi"; 275 err = get_module(env, loader, "com/sun/jdi", &module, &mod_name); 276 if (err != JVMTI_ERROR_NONE) { 277 throw_exc(env, "check #S5: failed to return JVMTI_ERROR_NONE for test package"); 278 return FAILED; 279 } 280 if (module == NULL || mod_name == NULL) { 281 throw_exc(env, "check #S6: failed to return named module for com/sun/jdi package"); 282 return FAILED; 283 } 284 if (strcmp(mod_name, exp_name) != 0) { 285 printf("check #S7: failed to return right module, expected: %s, returned: %s\n", 286 exp_name, mod_name); 287 throw_exc(env, "check #S7: failed to return jdk.jdi module for com/sun/jdi package"); 288 return FAILED; 289 } 290 291 // Non-existing package: "bad/package/name" 292 err = get_module(env, loader, "bad/package/name", &module, &mod_name); 293 if (err != JVMTI_ERROR_NONE) { 294 throw_exc(env, "check #S8: failed to return JVMTI_ERROR_NONE for bad package"); 295 return FAILED; 296 } 297 if (module != NULL || mod_name != NULL) { 298 throw_exc(env, "check #S9: failed to return NULL-module for bad package"); 299 return FAILED; 300 } 301 return PASSED; 302} 303 304static 305jint check_bootstrap_loader(JNIEnv *env, jobject loader) { 306 jvmtiError err = JVMTI_ERROR_NONE; 307 jobject module = NULL; 308 const char* exp_name = NULL; 309 const char* mod_name = NULL; 310 311 // NULL pointer for package name 312 err = get_module(env, loader, NULL, &module, &mod_name); 313 if (err != JVMTI_ERROR_NULL_POINTER) { 314 throw_exc(env, "check #BN1: failed to return JVMTI_ERROR_NULL_POINTER for NULL package"); 315 return FAILED; 316 } 317 318 // NULL pointer for module_ptr 319 err = (*jvmti)->GetNamedModule(jvmti, loader, "", NULL); 320 if (err != JVMTI_ERROR_NULL_POINTER) { 321 throw_exc(env, "check #BN2: failed to return JVMTI_ERROR_NULL_POINTER for NULL module_ptr"); 322 return FAILED; 323 } 324 325 // Unnamed/default package "" 326 err = get_module(env, loader, "", &module, &mod_name); 327 if (err != JVMTI_ERROR_NONE) { 328 throw_exc(env, "check #B1: failed to return JVMTI_ERROR_NONE for default package"); 329 return FAILED; 330 } 331 if (module != NULL || mod_name != NULL) { 332 throw_exc(env, "check #B2: failed to return NULL-module for default package"); 333 return FAILED; 334 } 335 336 // Normal package from java.base module: "java/lang" 337 exp_name = "java.base"; 338 err = get_module(env, loader, "java/lang", &module, &mod_name); 339 if (err != JVMTI_ERROR_NONE) { 340 throw_exc(env, "check #B3: failed to return JVMTI_ERROR_NONE for java/lang package"); 341 return FAILED; 342 } 343 if (module == NULL || mod_name == NULL) { 344 throw_exc(env, "check #B4: failed to return named module for java/lang package"); 345 return FAILED; 346 } 347 if (strcmp(exp_name, mod_name) != 0) { 348 printf("check #B5: failed to return right module, expected: %s, returned: %s\n", 349 exp_name, mod_name); 350 throw_exc(env, "check #B5: failed to return expected module for java/lang package"); 351 return FAILED; 352 } 353 354 // Non-existing package: "bad/package/name" 355 err = get_module(env, loader, "bad/package/name", &module, &mod_name); 356 if (err != JVMTI_ERROR_NONE) { 357 throw_exc(env, "check #B6: failed to return JVMTI_ERROR_NONE for bad package"); 358 return FAILED; 359 } 360 if (module != NULL || mod_name != NULL) { 361 throw_exc(env, "check #B7: failed to return NULL-module for bad package"); 362 return FAILED; 363 } 364 return PASSED; 365} 366 367JNIEXPORT jint JNICALL 368Java_MyPackage_GetNamedModuleTest_check(JNIEnv *env, jclass cls) { 369 jobject loader = NULL; 370 371 if (jvmti == NULL) { 372 throw_exc(env, "JVMTI client was not properly loaded!\n"); 373 return FAILED; 374 } 375 376 get_all_modules(env); 377 378 printf("\n*** Check for bad ClassLoader ***\n\n"); 379 result = check_bad_loader(env, (jobject)cls); 380 if (result != PASSED) { 381 throw_exc(env, "check #L1: failed to return JVMTI_ERROR_ILLEGAL_ARGUMENT for bad loader"); 382 return result; 383 } 384 385 loader = get_class_loader(cls); 386 if (loader == NULL) { 387 throw_exc(env, "check #L2: failed to return non-NULL loader for valid test class"); 388 return FAILED; 389 } 390 391 printf("\n*** Checks for System ClassLoader ***\n\n"); 392 result = check_system_loader(env, loader); 393 if (result != PASSED) { 394 return result; 395 } 396 397 printf("\n*** Checks for Bootstrap ClassLoader ***\n\n"); 398 result = check_bootstrap_loader(env, NULL); 399 400 return result; 401} 402 403#ifdef __cplusplus 404} 405#endif 406