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");
|