< prev index next >

src/hotspot/share/oops/instanceKlass.cpp

Print this page




 219 // Return nest-host class, resolving, validating and saving it if needed.
 220 // In cases where this is called from a thread that cannot do classloading
 221 // (such as a native JIT thread) then we simply return NULL, which in turn
 222 // causes the access check to return false. Such code will retry the access
 223 // from a more suitable environment later. Otherwise the _nest_host is always
 224 // set once this method returns.
 225 // Any errors from nest-host resolution must be preserved so they can be queried
 226 // from higher-level access checking code, and reported as part of access checking
 227 // exceptions.
 228 // VirtualMachineErrors are propagated with a NULL return.
 229 // Under any conditions where the _nest_host can be set to non-NULL the resulting value
 230 // of it and, if applicable, _nest_host_res_error, are idempotent. But as we can be
 231 // executing this code concurrently we need to ensure ordering is maintained so that
 232 // errors messages can safely be read.
 233 InstanceKlass* InstanceKlass::nest_host(TRAPS) {
 234   InstanceKlass* nest_host_k = _nest_host;
 235   if (nest_host_k != NULL) {
 236     return nest_host_k;
 237   }
 238 
 239   const bool doLog = log_is_enabled(Trace, class, nestmates);
 240 
 241   // need to resolve and save our nest-host class.
 242   if (_nest_host_index != 0) { // we have a real nest_host
 243     // Before trying to resolve check if we're in a suitable context
 244     if (!THREAD->can_call_java() && !_constants->tag_at(_nest_host_index).is_klass()) {
 245       if (doLog) {
 246         ResourceMark rm(THREAD);
 247         log_trace(class, nestmates)("Rejected resolution of nest-host of %s in unsuitable thread",
 248                                     this->external_name());
 249       }
 250       return NULL; // sentinel to say "try again from a different context"
 251     }
 252 
 253     if (doLog) {
 254       ResourceMark rm(THREAD);
 255       log_trace(class, nestmates)("Resolving nest-host of %s using cp entry for %s",
 256                                   this->external_name(),
 257                                   _constants->klass_name_at(_nest_host_index)->as_C_string());
 258     }
 259 
 260     Klass* k = _constants->klass_at(_nest_host_index, THREAD);
 261     if (HAS_PENDING_EXCEPTION) {
 262       if (PENDING_EXCEPTION->is_a(SystemDictionary::VirtualMachineError_klass())) {
 263         return NULL; // propagate VMEs
 264       }
 265       ResourceMark rm(THREAD);
 266       stringStream ss;
 267       char* target_host_class = _constants->klass_name_at(_nest_host_index)->as_C_string();
 268       ss.print("Nest host resolution of %s with host %s failed: ",
 269                this->external_name(), target_host_class);
 270       java_lang_Throwable::print(PENDING_EXCEPTION, &ss);
 271       _nest_host_res_error = ss.as_string(true /* on C-heap */);
 272       // ensure we see _nest_host_res_error is set if _nest_host is non-NULL
 273       OrderAccess::storestore();
 274       CLEAR_PENDING_EXCEPTION;
 275       if (doLog) {
 276         log_trace(class, nestmates)("%s", _nest_host_res_error);
 277       }
 278     } else {
 279       // A valid nest-host is an instance class in the current package that lists this
 280       // class as a nest member. If any of these conditions are not met the class is
 281       // its own nest-host.
 282       const char* error = NULL;
 283 
 284       // JVMS 5.4.4 indicates package check comes first
 285       if (is_same_class_package(k)) {
 286         // Now check actual membership. We can't be a member if our "host" is
 287         // not an instance class.
 288         if (k->is_instance_klass()) {
 289           nest_host_k = InstanceKlass::cast(k);
 290           bool is_member = nest_host_k->has_nest_member(this, THREAD);
 291           // exception is rare, perhaps impossible
 292           if (!HAS_PENDING_EXCEPTION) {
 293             if (is_member) {
 294               _nest_host = nest_host_k; // save resolved nest-host value
 295               if (doLog) {
 296                 ResourceMark rm(THREAD);
 297                 log_trace(class, nestmates)("Resolved nest-host of %s to %s",
 298                                             this->external_name(), k->external_name());
 299               }
 300               return nest_host_k;
 301             } else {
 302               error = "current type is not listed as a nest member";
 303             }
 304           } else {
 305             if (PENDING_EXCEPTION->is_a(SystemDictionary::VirtualMachineError_klass())) {
 306               return NULL; // propagate VMEs
 307             }
 308             stringStream ss;
 309             ss.print("exception on member check: ");
 310             java_lang_Throwable::print(PENDING_EXCEPTION, &ss);
 311             error = ss.as_string();
 312           }
 313         } else {
 314           error = "host is not an instance class";
 315         }
 316       } else {
 317         error = "types are in different packages";
 318       }
 319 
 320       // something went wrong, so record what and log it
 321       {
 322         ResourceMark rm(THREAD);
 323         stringStream ss;
 324         ss.print("Type %s (loader: %s) is not a nest member of type %s (loader: %s): %s",
 325                  this->external_name(),
 326                  this->class_loader_data()->loader_name_and_id(),
 327                  k->external_name(),
 328                  k->class_loader_data()->loader_name_and_id(),
 329                  error);
 330         _nest_host_res_error = ss.as_string(true /* on C-heap */);
 331         // ensure we see _nest_host_res_error is set if _nest_host is non-NULL
 332         OrderAccess::storestore();
 333 
 334         if (doLog) {
 335           log_trace(class, nestmates)("%s", _nest_host_res_error);
 336         }
 337       }
 338     }
 339   } else {
 340     if (doLog) {
 341       ResourceMark rm(THREAD);
 342       log_trace(class, nestmates)("Type %s is not part of a nest: setting nest-host to self",
 343                                   this->external_name());
 344     }
 345   }
 346 
 347   // Either not in an explicit nest, or else an error occurred, so
 348   // the nest-host is set to `this`. Any thread that sees this assignment
 349   // will also see any setting of _nest_host_res_error, if applicable.
 350   return (_nest_host = this);
 351 }
 352 
 353 // Dynamic nest member support: set this class's nest host to the given class.
 354 // This occurs as part of the class definition, as soon as the instanceKlass
 355 // has been created and doesn't require further resolution. The code:
 356 //    lookup().defineHiddenClass(bytes_for_X, NESTMATE);
 357 // results in:
 358 //    class_of_X.set_nest_host(lookup().lookupClass().getNestHost())
 359 // If it has an explicit _nest_host_index or _nest_members, these will be ignored.
 360 // We also know the "host" is a valid nest-host in the same package so we can
 361 // assert some of those facts.
 362 void InstanceKlass::set_nest_host(InstanceKlass* host, TRAPS) {
 363   assert(is_hidden(), "must be a hidden class");
 364   assert(host != NULL, "NULL nest host specified");
 365   assert(_nest_host == NULL, "current class has resolved nest-host");


 394 // Any exceptions (i.e. VMEs) are propagated.
 395 bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) {
 396 
 397   assert(this != k, "this should be handled by higher-level code");
 398 
 399   // Per JVMS 5.4.4 we first resolve and validate the current class, then
 400   // the target class k.
 401 
 402   InstanceKlass* cur_host = nest_host(CHECK_false);
 403   if (cur_host == NULL) {
 404     return false;
 405   }
 406 
 407   Klass* k_nest_host = k->nest_host(CHECK_false);
 408   if (k_nest_host == NULL) {
 409     return false;
 410   }
 411 
 412   bool access = (cur_host == k_nest_host);
 413 
 414   if (log_is_enabled(Trace, class, nestmates)) {
 415     ResourceMark rm(THREAD);
 416     log_trace(class, nestmates)("Class %s does %shave nestmate access to %s",
 417                                 this->external_name(),
 418                                 access ? "" : "NOT ",
 419                                 k->external_name());
 420   }
 421 
 422   return access;
 423 }
 424 
 425 InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) {
 426   bool is_hidden_or_anonymous = parser.is_hidden() || parser.is_unsafe_anonymous();
 427   const int size = InstanceKlass::size(parser.vtable_size(),
 428                                        parser.itable_size(),
 429                                        nonstatic_oop_map_size(parser.total_oop_map_count()),
 430                                        parser.is_interface(),
 431                                        is_hidden_or_anonymous,
 432                                        should_store_fingerprint(is_hidden_or_anonymous));
 433 
 434   const Symbol* const class_name = parser.class_name();
 435   assert(class_name != NULL, "invariant");
 436   ClassLoaderData* loader_data = parser.loader_data();
 437   assert(loader_data != NULL, "invariant");
 438 
 439   InstanceKlass* ik;
 440 
 441   // Allocation




 219 // Return nest-host class, resolving, validating and saving it if needed.
 220 // In cases where this is called from a thread that cannot do classloading
 221 // (such as a native JIT thread) then we simply return NULL, which in turn
 222 // causes the access check to return false. Such code will retry the access
 223 // from a more suitable environment later. Otherwise the _nest_host is always
 224 // set once this method returns.
 225 // Any errors from nest-host resolution must be preserved so they can be queried
 226 // from higher-level access checking code, and reported as part of access checking
 227 // exceptions.
 228 // VirtualMachineErrors are propagated with a NULL return.
 229 // Under any conditions where the _nest_host can be set to non-NULL the resulting value
 230 // of it and, if applicable, _nest_host_res_error, are idempotent. But as we can be
 231 // executing this code concurrently we need to ensure ordering is maintained so that
 232 // errors messages can safely be read.
 233 InstanceKlass* InstanceKlass::nest_host(TRAPS) {
 234   InstanceKlass* nest_host_k = _nest_host;
 235   if (nest_host_k != NULL) {
 236     return nest_host_k;
 237   }
 238 
 239   ResourceMark rm(THREAD);
 240 
 241   // need to resolve and save our nest-host class.
 242   if (_nest_host_index != 0) { // we have a real nest_host
 243     // Before trying to resolve check if we're in a suitable context
 244     if (!THREAD->can_call_java() && !_constants->tag_at(_nest_host_index).is_klass()) {


 245       log_trace(class, nestmates)("Rejected resolution of nest-host of %s in unsuitable thread",
 246                                   this->external_name());

 247       return NULL; // sentinel to say "try again from a different context"
 248     }
 249 


 250     log_trace(class, nestmates)("Resolving nest-host of %s using cp entry for %s",
 251                                 this->external_name(),
 252                                 _constants->klass_name_at(_nest_host_index)->as_C_string());

 253 
 254     Klass* k = _constants->klass_at(_nest_host_index, THREAD);
 255     if (HAS_PENDING_EXCEPTION) {
 256       if (PENDING_EXCEPTION->is_a(SystemDictionary::VirtualMachineError_klass())) {
 257         return NULL; // propagate VMEs
 258       }

 259       stringStream ss;
 260       char* target_host_class = _constants->klass_name_at(_nest_host_index)->as_C_string();
 261       ss.print("Nest host resolution of %s with host %s failed: ",
 262                this->external_name(), target_host_class);
 263       java_lang_Throwable::print(PENDING_EXCEPTION, &ss);
 264       _nest_host_res_error = ss.as_string(true /* on C-heap */);
 265       // ensure we see _nest_host_res_error is set if _nest_host is non-NULL
 266       OrderAccess::storestore();
 267       CLEAR_PENDING_EXCEPTION;
 268 
 269       log_trace(class, nestmates)("%s", _nest_host_res_error);

 270     } else {
 271       // A valid nest-host is an instance class in the current package that lists this
 272       // class as a nest member. If any of these conditions are not met the class is
 273       // its own nest-host.
 274       const char* error = NULL;
 275 
 276       // JVMS 5.4.4 indicates package check comes first
 277       if (is_same_class_package(k)) {
 278         // Now check actual membership. We can't be a member if our "host" is
 279         // not an instance class.
 280         if (k->is_instance_klass()) {
 281           nest_host_k = InstanceKlass::cast(k);
 282           bool is_member = nest_host_k->has_nest_member(this, THREAD);
 283           // exception is rare, perhaps impossible
 284           if (!HAS_PENDING_EXCEPTION) {
 285             if (is_member) {
 286               _nest_host = nest_host_k; // save resolved nest-host value
 287 

 288               log_trace(class, nestmates)("Resolved nest-host of %s to %s",
 289                                           this->external_name(), k->external_name());

 290               return nest_host_k;
 291             } else {
 292               error = "current type is not listed as a nest member";
 293             }
 294           } else {
 295             if (PENDING_EXCEPTION->is_a(SystemDictionary::VirtualMachineError_klass())) {
 296               return NULL; // propagate VMEs
 297             }
 298             stringStream ss;
 299             ss.print("exception on member check: ");
 300             java_lang_Throwable::print(PENDING_EXCEPTION, &ss);
 301             error = ss.as_string();
 302           }
 303         } else {
 304           error = "host is not an instance class";
 305         }
 306       } else {
 307         error = "types are in different packages";
 308       }
 309 
 310       // something went wrong, so record what and log it
 311       {

 312         stringStream ss;
 313         ss.print("Type %s (loader: %s) is not a nest member of type %s (loader: %s): %s",
 314                  this->external_name(),
 315                  this->class_loader_data()->loader_name_and_id(),
 316                  k->external_name(),
 317                  k->class_loader_data()->loader_name_and_id(),
 318                  error);
 319         _nest_host_res_error = ss.as_string(true /* on C-heap */);
 320         // ensure we see _nest_host_res_error is set if _nest_host is non-NULL
 321         OrderAccess::storestore();
 322 

 323         log_trace(class, nestmates)("%s", _nest_host_res_error);
 324       }
 325     }

 326   } else {


 327     log_trace(class, nestmates)("Type %s is not part of a nest: setting nest-host to self",
 328                                 this->external_name());
 329   }

 330 
 331   // Either not in an explicit nest, or else an error occurred, so
 332   // the nest-host is set to `this`. Any thread that sees this assignment
 333   // will also see any setting of _nest_host_res_error, if applicable.
 334   return (_nest_host = this);
 335 }
 336 
 337 // Dynamic nest member support: set this class's nest host to the given class.
 338 // This occurs as part of the class definition, as soon as the instanceKlass
 339 // has been created and doesn't require further resolution. The code:
 340 //    lookup().defineHiddenClass(bytes_for_X, NESTMATE);
 341 // results in:
 342 //    class_of_X.set_nest_host(lookup().lookupClass().getNestHost())
 343 // If it has an explicit _nest_host_index or _nest_members, these will be ignored.
 344 // We also know the "host" is a valid nest-host in the same package so we can
 345 // assert some of those facts.
 346 void InstanceKlass::set_nest_host(InstanceKlass* host, TRAPS) {
 347   assert(is_hidden(), "must be a hidden class");
 348   assert(host != NULL, "NULL nest host specified");
 349   assert(_nest_host == NULL, "current class has resolved nest-host");


 378 // Any exceptions (i.e. VMEs) are propagated.
 379 bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) {
 380 
 381   assert(this != k, "this should be handled by higher-level code");
 382 
 383   // Per JVMS 5.4.4 we first resolve and validate the current class, then
 384   // the target class k.
 385 
 386   InstanceKlass* cur_host = nest_host(CHECK_false);
 387   if (cur_host == NULL) {
 388     return false;
 389   }
 390 
 391   Klass* k_nest_host = k->nest_host(CHECK_false);
 392   if (k_nest_host == NULL) {
 393     return false;
 394   }
 395 
 396   bool access = (cur_host == k_nest_host);
 397 

 398   ResourceMark rm(THREAD);
 399   log_trace(class, nestmates)("Class %s does %shave nestmate access to %s",
 400                               this->external_name(),
 401                               access ? "" : "NOT ",
 402                               k->external_name());


 403   return access;
 404 }
 405 
 406 InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) {
 407   bool is_hidden_or_anonymous = parser.is_hidden() || parser.is_unsafe_anonymous();
 408   const int size = InstanceKlass::size(parser.vtable_size(),
 409                                        parser.itable_size(),
 410                                        nonstatic_oop_map_size(parser.total_oop_map_count()),
 411                                        parser.is_interface(),
 412                                        is_hidden_or_anonymous,
 413                                        should_store_fingerprint(is_hidden_or_anonymous));
 414 
 415   const Symbol* const class_name = parser.class_name();
 416   assert(class_name != NULL, "invariant");
 417   ClassLoaderData* loader_data = parser.loader_data();
 418   assert(loader_data != NULL, "invariant");
 419 
 420   InstanceKlass* ik;
 421 
 422   // Allocation


< prev index next >