< prev index next >

src/hotspot/share/oops/instanceKlass.cpp

Print this page
rev 59277 : [mq]: v3


 209           // can't have two names the same, so we're done
 210           return false;
 211         }
 212       }
 213     }
 214   }
 215   log_trace(class, nestmates)("- class is NOT a nest member!");
 216   return false;
 217 }
 218 
 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 InstanceKlass* InstanceKlass::nest_host(TRAPS) {
 230   InstanceKlass* nest_host_k = _nest_host;
 231   if (nest_host_k != NULL) {
 232     return nest_host_k;
 233   }
 234 
 235   const bool doLog = log_is_enabled(Trace, class, nestmates);
 236 
 237   // need to resolve and save our nest-host class. This could be attempted
 238   // concurrently but as the result is idempotent and we don't use the class
 239   // then we do not need any synchronization beyond what is implicitly used
 240   // during class loading.
 241   if (_nest_host_index != 0) { // we have a real nest_host
 242     // Before trying to resolve check if we're in a suitable context
 243     if (!THREAD->can_call_java() && !_constants->tag_at(_nest_host_index).is_klass()) {
 244       if (doLog) {
 245         ResourceMark rm(THREAD);
 246         log_trace(class, nestmates)("Rejected resolution of nest-host of %s in unsuitable thread",
 247                                     this->external_name());
 248       }
 249       return NULL; // sentinel to say "try again from a different context"
 250     }
 251 
 252     if (doLog) {
 253       ResourceMark rm(THREAD);
 254       log_trace(class, nestmates)("Resolving nest-host of %s using cp entry for %s",
 255                                   this->external_name(),
 256                                   _constants->klass_name_at(_nest_host_index)->as_C_string());
 257     }
 258 
 259     Klass* k = _constants->klass_at(_nest_host_index, THREAD);
 260     if (HAS_PENDING_EXCEPTION) {
 261       if (PENDING_EXCEPTION->is_a(SystemDictionary::VirtualMachineError_klass())) {
 262         return NULL; // propagate VMEs
 263       }
 264       ResourceMark rm(THREAD);
 265       stringStream ss;
 266       char* target_host_class = _constants->klass_name_at(_nest_host_index)->as_C_string();
 267       ss.print("Nest host resolution of %s with host %s failed: ",
 268                this->external_name(), target_host_class);
 269       java_lang_Throwable::print(PENDING_EXCEPTION, &ss);
 270       _nest_host_res_error = ss.as_string(true /* on C-heap */);


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


 308             error = ss.as_string();
 309           }
 310         } else {
 311           error = "host is not an instance class";
 312         }
 313       } else {
 314         error = "types are in different packages";
 315       }
 316 
 317       // something went wrong, so record what and log it
 318       {
 319         ResourceMark rm(THREAD);
 320         stringStream ss;
 321         ss.print("Type %s (loader: %s) is not a nest member of type %s (loader: %s): %s",
 322                  this->external_name(),
 323                  this->class_loader_data()->loader_name_and_id(),
 324                  k->external_name(),
 325                  k->class_loader_data()->loader_name_and_id(),
 326                  error);
 327         _nest_host_res_error = ss.as_string(true /* on C-heap */);


 328 
 329         if (doLog) {
 330           log_trace(class, nestmates)("%s", _nest_host_res_error);
 331         }
 332       }
 333     }
 334   } else {
 335     if (doLog) {
 336       ResourceMark rm(THREAD);
 337       log_trace(class, nestmates)("Type %s is not part of a nest: setting nest-host to self",
 338                                   this->external_name());
 339     }
 340   }
 341 
 342   // Either not in an explicit nest, or else an error occurred, so
 343   // the nest-host is set to `this`.

 344   return (_nest_host = this);
 345 }
 346 
 347 // Dynamic nest member support: set this class's nest host to the given class.
 348 // This occurs as part of the class definition, as soon as the instanceKlass
 349 // has been created and doesn't require further resolution. The code:
 350 //    lookup().defineHiddenClass(bytes_for_X, NESTMATE);
 351 // results in:
 352 //    class_of_X.set_nest_host(lookup().lookupClass().getNestHost())
 353 // If it has an explicit _nest_host_index or _nest_members, these will be ignored.
 354 // We also know the "host" is a valid nest-host in the same package so we can
 355 // assert some of those facts.
 356 void InstanceKlass::set_nest_host(InstanceKlass* host, TRAPS) {
 357   assert(is_hidden(), "must be a hidden class");
 358   assert(host != NULL, "NULL nest host specified");
 359   assert(_nest_host == NULL, "current class has resolved nest-host");
 360   assert(_nest_host_res_error == NULL, "unexpected nest host resolution error exists: %s",
 361          _nest_host_res_error);
 362   assert((host->_nest_host == NULL && host->_nest_host_index == 0) ||
 363          (host->_nest_host == host), "proposed host is not a valid nest-host");




 209           // can't have two names the same, so we're done
 210           return false;
 211         }
 212       }
 213     }
 214   }
 215   log_trace(class, nestmates)("- class is NOT a nest member!");
 216   return false;
 217 }
 218 
 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) {


 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");
 366   assert(_nest_host_res_error == NULL, "unexpected nest host resolution error exists: %s",
 367          _nest_host_res_error);
 368   assert((host->_nest_host == NULL && host->_nest_host_index == 0) ||
 369          (host->_nest_host == host), "proposed host is not a valid nest-host");


< prev index next >