< prev index next >
src/hotspot/share/oops/instanceKlass.cpp
Print this page
*** 153,162 ****
--- 153,163 ----
return false;
}
// called to verify that k is a member of this nest
bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const {
+ assert(!is_hidden(), "unexpected hidden class");
if (_nest_members == NULL || _nest_members == Universe::the_empty_short_array()) {
if (log_is_enabled(Trace, class, nestmates)) {
ResourceMark rm(THREAD);
log_trace(class, nestmates)("Checked nest membership of %s in non-nest-host class %s",
k->external_name(), this->external_name());
*** 210,219 ****
--- 211,238 ----
}
log_trace(class, nestmates)("- class is NOT a nest member!");
return false;
}
+ InstanceKlass* InstanceKlass::runtime_nest_host(TRAPS) {
+ // TODO: nest_host returns NULL if validation fails. Need to follow up
+ // the specification when to evaluate the runtime nest host. Right now
+ // it's only determined when a dynamic nestmate is added.
+ InstanceKlass* nest_host_k = nest_host(NULL, CHECK_NULL);
+ if (nest_host_k == NULL) {
+ assert(_nest_host == NULL, "should fail to validate NestNost");
+ // drop the static nest information; set dynamic nest to this class
+ if (log_is_enabled(Trace, class, nestmates)) {
+ ResourceMark rm(THREAD);
+ log_trace(class, nestmates)("Fail to validate static nest host of %s: setting nest-host to self",
+ this->external_name());
+ }
+ _nest_host = nest_host_k = this;
+ }
+ return nest_host_k;
+ }
+
// Return nest-host class, resolving, validating and saving it if needed.
// In cases where this is called from a thread that can not do classloading
// (such as a native JIT thread) then we simply return NULL, which in turn
// causes the access check to return false. Such code will retry the access
// from a more suitable environment later.
*** 243,254 ****
}
Klass* k = _constants->klass_at(_nest_host_index, THREAD);
if (HAS_PENDING_EXCEPTION) {
Handle exc_h = Handle(THREAD, PENDING_EXCEPTION);
! if (exc_h->is_a(SystemDictionary::NoClassDefFoundError_klass())) {
! // throw a new CDNFE with the original as its cause, and a clear msg
ResourceMark rm(THREAD);
char buf[200];
CLEAR_PENDING_EXCEPTION;
jio_snprintf(buf, sizeof(buf),
"Unable to load nest-host class (%s) of %s",
--- 262,278 ----
}
Klass* k = _constants->klass_at(_nest_host_index, THREAD);
if (HAS_PENDING_EXCEPTION) {
Handle exc_h = Handle(THREAD, PENDING_EXCEPTION);
! if (validationException == NULL && exc_h->is_a(SystemDictionary::LinkageError_klass())) {
! // clear exception if fails to resolve the nest host class
! CLEAR_PENDING_EXCEPTION;
! }
! // throw a new NCDFE with the original as its cause, and a clear msg
! if (exc_h->is_a(SystemDictionary::NoClassDefFoundError_klass()) && validationException != NULL) {
! // throw a new NCDFE with the original as its cause, and a clear msg
ResourceMark rm(THREAD);
char buf[200];
CLEAR_PENDING_EXCEPTION;
jio_snprintf(buf, sizeof(buf),
"Unable to load nest-host class (%s) of %s",
*** 329,338 ****
--- 353,398 ----
}
}
return nest_host_k;
}
+
+ // Dynamic nest member support: set this class's nest host to the given class.
+ // This occurs as part of the class definition, as soon as the instanceKlass
+ // has been created and doesn't require further resolution. The code:
+ // lookup().defineHiddenClass(bytes_for_X, NESTMATE);
+ // results in:
+ // class_of_X.set_nest_host(lookup().lookupClass().getNestHost())
+ // If it has an explicit _nest_host_index or _nest_members, these will be ignored.
+ // We also know the "host" is a valid nest-host in the same package so we can
+ // assert some of those facts.
+ void InstanceKlass::set_nest_host(InstanceKlass* host, TRAPS) {
+ assert(is_hidden(), "must be a hidden class");
+ assert(host != NULL, "NULL nest host specified");
+ assert(_nest_host == NULL, "current class has resolved nest-host");
+ assert((host->_nest_host == NULL && host->_nest_host_index == 0) ||
+ (host->_nest_host == host), "proposed host is not a valid nest-host");
+ // Can't assert this as package is not set yet:
+ // assert(is_same_class_package(host), "proposed host is in wrong package");
+
+ if (log_is_enabled(Trace, class, nestmates)) {
+ ResourceMark rm(THREAD);
+ // a hidden class does not expect a statically defined nest-host
+ if (_nest_host_index > 0) {
+ log_trace(class, nestmates)("Type %s is a dynamic nest member of %s: the NestHost attribute in the current class is ignored",
+ this->external_name(),
+ host->external_name());
+ } else if (_nest_members != NULL && _nest_members != Universe::the_empty_short_array()) {
+ log_trace(class, nestmates)("Type %s is a dynamic nest member of %s: the NestMembers attribute in the current class is ignored",
+ this->external_name(),
+ host->external_name());
+ }
+ }
+ // set dynamic nest host
+ _nest_host = host;
+ }
+
// check if 'this' and k are nestmates (same nest_host), or k is our nest_host,
// or we are k's nest_host - all of which is covered by comparing the two
// resolved_nest_hosts
bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) {
*** 366,381 ****
return access;
}
InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) {
const int size = InstanceKlass::size(parser.vtable_size(),
parser.itable_size(),
nonstatic_oop_map_size(parser.total_oop_map_count()),
parser.is_interface(),
! parser.is_unsafe_anonymous(),
! should_store_fingerprint(parser.is_unsafe_anonymous()));
const Symbol* const class_name = parser.class_name();
assert(class_name != NULL, "invariant");
ClassLoaderData* loader_data = parser.loader_data();
assert(loader_data != NULL, "invariant");
--- 426,442 ----
return access;
}
InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) {
+ bool is_hidden_or_anonymous = parser.is_hidden() || parser.is_unsafe_anonymous();
const int size = InstanceKlass::size(parser.vtable_size(),
parser.itable_size(),
nonstatic_oop_map_size(parser.total_oop_map_count()),
parser.is_interface(),
! is_hidden_or_anonymous,
! should_store_fingerprint(is_hidden_or_anonymous));
const Symbol* const class_name = parser.class_name();
assert(class_name != NULL, "invariant");
ClassLoaderData* loader_data = parser.loader_data();
assert(loader_data != NULL, "invariant");
*** 444,453 ****
--- 505,515 ----
_reference_type(parser.reference_type())
{
set_vtable_length(parser.vtable_size());
set_kind(kind);
set_access_flags(parser.access_flags());
+ if (parser.is_hidden()) set_is_hidden();
set_is_unsafe_anonymous(parser.is_unsafe_anonymous());
set_layout_helper(Klass::instance_layout_helper(parser.layout_size(),
false));
assert(NULL == _methods, "underlying memory not zeroed?");
*** 2246,2268 ****
}
return true;
}
! bool InstanceKlass::should_store_fingerprint(bool is_unsafe_anonymous) {
#if INCLUDE_AOT
// We store the fingerprint into the InstanceKlass only in the following 2 cases:
if (CalculateClassFingerprint) {
// (1) We are running AOT to generate a shared library.
return true;
}
if (Arguments::is_dumping_archive()) {
// (2) We are running -Xshare:dump or -XX:ArchiveClassesAtExit to create a shared archive
return true;
}
! if (UseAOT && is_unsafe_anonymous) {
! // (3) We are using AOT code from a shared library and see an unsafe anonymous class
return true;
}
#endif
// In all other cases we might set the _misc_has_passed_fingerprint_check bit,
--- 2308,2330 ----
}
return true;
}
! bool InstanceKlass::should_store_fingerprint(bool is_hidden_or_anonymous) {
#if INCLUDE_AOT
// We store the fingerprint into the InstanceKlass only in the following 2 cases:
if (CalculateClassFingerprint) {
// (1) We are running AOT to generate a shared library.
return true;
}
if (Arguments::is_dumping_archive()) {
// (2) We are running -Xshare:dump or -XX:ArchiveClassesAtExit to create a shared archive
return true;
}
! if (UseAOT && is_hidden_or_anonymous) {
! // (3) We are using AOT code from a shared library and see a hidden or unsafe anonymous class
return true;
}
#endif
// In all other cases we might set the _misc_has_passed_fingerprint_check bit,
*** 2583,2592 ****
--- 2645,2655 ----
}
#endif
// Decrement symbol reference counts associated with the unloaded class.
if (_name != NULL) _name->decrement_refcount();
+
// unreference array name derived from this class name (arrays of an unloaded
// class can't be referenced anymore).
if (_array_name != NULL) _array_name->decrement_refcount();
FREE_C_HEAP_ARRAY(char, _source_debug_extension);
}
*** 2669,2678 ****
--- 2732,2760 ----
if (is_unsafe_anonymous()) {
assert(unsafe_anonymous_host() != NULL, "unsafe anonymous class must have a host class");
return unsafe_anonymous_host()->module();
}
+ if (is_hidden() &&
+ in_unnamed_package() &&
+ class_loader_data()->is_shortlived()) {
+ // For a weak hidden class defined to an unnamed package,
+ // the short-lived CLD will not have an unnamed module created for it.
+ // Two choices to find the correct ModuleEntry:
+ // 1. If hidden class is within a nest, use nest host's module
+ // 2. Find the unnamed module off from the class loader
+ // For now option #2 is used since a nest host is not set until
+ // after the instance class is created in jvm_lookup_define_class().
+ if (class_loader_data()->is_boot_class_loader_data()) {
+ return ClassLoaderData::the_null_class_loader_data()->unnamed_module();
+ } else {
+ oop module = java_lang_ClassLoader::unnamedModule(class_loader_data()->class_loader());
+ assert(java_lang_Module::is_instance(module), "Not an instance of java.lang.Module");
+ return java_lang_Module::module_entry(module);
+ }
+ }
+
// Class is in a named package
if (!in_unnamed_package()) {
return _package_entry->module();
}
*** 2880,2890 ****
Klass* ok = i_cp->klass_at(ooff, CHECK_NULL);
outer_klass = InstanceKlass::cast(ok);
*inner_is_member = true;
}
if (NULL == outer_klass) {
! // It may be unsafe anonymous; try for that.
int encl_method_class_idx = enclosing_method_class_index();
if (encl_method_class_idx != 0) {
Klass* ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL);
outer_klass = InstanceKlass::cast(ok);
*inner_is_member = false;
--- 2962,2972 ----
Klass* ok = i_cp->klass_at(ooff, CHECK_NULL);
outer_klass = InstanceKlass::cast(ok);
*inner_is_member = true;
}
if (NULL == outer_klass) {
! // It may be a local or anonymous class; try for that.
int encl_method_class_idx = enclosing_method_class_index();
if (encl_method_class_idx != 0) {
Klass* ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL);
outer_klass = InstanceKlass::cast(ok);
*inner_is_member = false;
< prev index next >