< prev index next >

src/hotspot/share/classfile/systemDictionary.cpp

Print this page
rev 58565 : 8238358: Implementation of JEP 371: Hidden Classes
Reviewed-by: duke
Contributed-by: mandy.chung@oracle.com, lois.foltan@oracle.com, david.holmes@oracle.com, harold.seigel@oracle.com, serguei.spitsyn@oracle.com, alex.buckley@oracle.com, jamsheed.c.m@oracle.com

@@ -109,10 +109,50 @@
 
 // Default ProtectionDomainCacheSize value
 
 const int defaultProtectionDomainCacheSize = 1009;
 
+ClassLoadInfo::ClassLoadInfo() {
+  _protection_domain = Handle();
+  _unsafe_anonymous_host = NULL;
+  _cp_patches = NULL;
+  _class_hidden_info._dynamic_nest_host = NULL;
+  _class_hidden_info._class_data = Handle();
+  _is_hidden = false;
+  _is_strong_hidden = false;
+  _can_access_vm_annotations = false;
+}
+
+ClassLoadInfo::ClassLoadInfo(Handle protection_domain) {
+  _protection_domain = protection_domain;
+  _unsafe_anonymous_host = NULL;
+  _cp_patches = NULL;
+  _class_hidden_info._dynamic_nest_host = NULL;
+  _class_hidden_info._class_data = Handle();
+  _is_hidden = false;
+  _is_strong_hidden = false;
+  _can_access_vm_annotations = false;
+}
+
+ClassLoadInfo::ClassLoadInfo(Handle protection_domain,
+                             const InstanceKlass* unsafe_anonymous_host,
+                             GrowableArray<Handle>* cp_patches,
+                             InstanceKlass* dynamic_nest_host,
+                             Handle class_data,
+                             bool is_hidden,
+                             bool is_strong_hidden,
+                             bool can_access_vm_annotations) {
+  _protection_domain = protection_domain;
+  _unsafe_anonymous_host = unsafe_anonymous_host;
+  _cp_patches = cp_patches;
+  _class_hidden_info._dynamic_nest_host = dynamic_nest_host;
+  _class_hidden_info._class_data = class_data;
+  _is_hidden = is_hidden;
+  _is_strong_hidden = is_strong_hidden;
+  _can_access_vm_annotations = can_access_vm_annotations;
+}
+
 // ----------------------------------------------------------------------------
 // Java-level SystemLoader and PlatformLoader
 
 oop SystemDictionary::java_system_loader() {
   return _java_system_loader;

@@ -980,28 +1020,40 @@
   return k;
 }
 
 // Note: this method is much like resolve_from_stream, but
 // does not publish the classes via the SystemDictionary.
-// Handles unsafe_DefineAnonymousClass and redefineclasses
-// RedefinedClasses do not add to the class hierarchy
+// Handles Lookup.defineClass hidden, unsafe_DefineAnonymousClass
+// and redefineclasses. RedefinedClasses do not add to the class hierarchy.
 InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
                                               Handle class_loader,
-                                              Handle protection_domain,
                                               ClassFileStream* st,
-                                              const InstanceKlass* unsafe_anonymous_host,
-                                              GrowableArray<Handle>* cp_patches,
+                                              const ClassLoadInfo& cl_info,
                                               TRAPS) {
 
   EventClassLoad class_load_start_event;
 
   ClassLoaderData* loader_data;
-  if (unsafe_anonymous_host != NULL) {
-    // Create a new CLD for an unsafe anonymous class, that uses the same class loader
-    // as the unsafe_anonymous_host
-    guarantee(unsafe_anonymous_host->class_loader() == class_loader(), "should be the same");
-    loader_data = ClassLoaderData::unsafe_anonymous_class_loader_data(class_loader);
+
+  bool is_unsafe_anon_class = cl_info.unsafe_anonymous_host() != NULL;
+
+  if (is_unsafe_anon_class) {
+    // - for unsafe anonymous class: create a new CLD whith a class holder that uses
+    //                               the same class loader as the unsafe_anonymous_host.
+    guarantee(cl_info.unsafe_anonymous_host()->class_loader() == class_loader(),
+              "should be the same");
+    loader_data = ClassLoaderData::has_class_mirror_holder_cld(class_loader);
+  } else if (cl_info.is_hidden()) {
+    // - for hidden classes that are not strong: create a new CLD that has a class holder and
+    //                                           whose loader is the Lookup class' loader.
+    // - for hidden class: add the class to the Lookup class' loader's CLD.
+    if (!cl_info.is_strong_hidden()) {
+      loader_data = ClassLoaderData::has_class_mirror_holder_cld(class_loader);
+    } else {
+      // This hidden class goes into the regular CLD pool for this loader.
+      loader_data = register_loader(class_loader);
+    }
   } else {
     loader_data = ClassLoaderData::class_loader_data(class_loader());
   }
 
   assert(st != NULL, "invariant");

@@ -1013,19 +1065,20 @@
   // throw potential ClassFormatErrors.
 
   InstanceKlass* k = KlassFactory::create_from_stream(st,
                                                       class_name,
                                                       loader_data,
-                                                      protection_domain,
-                                                      unsafe_anonymous_host,
-                                                      cp_patches,
+                                                      cl_info,
                                                       CHECK_NULL);
 
-  if (unsafe_anonymous_host != NULL && k != NULL) {
-    // Unsafe anonymous classes must update ClassLoaderData holder (was unsafe_anonymous_host loader)
-    // so that they can be unloaded when the mirror is no longer referenced.
+  if ((cl_info.is_hidden() || is_unsafe_anon_class) && k != NULL) {
+    // Hidden classes that are not strong and unsafe anonymous classes must update
+    // ClassLoaderData holder so that they can be unloaded when the mirror is no
+    // longer referenced.
+    if (!cl_info.is_strong_hidden() || is_unsafe_anon_class) {
     k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror()));
+    }
 
     {
       MutexLocker mu_r(THREAD, Compile_lock);
 
       // Add to class hierarchy, initialize vtables, and do possible

@@ -1034,27 +1087,29 @@
       // But, do not add to dictionary.
     }
 
     // Rewrite and patch constant pool here.
     k->link_class(CHECK_NULL);
-    if (cp_patches != NULL) {
-      k->constants()->patch_resolved_references(cp_patches);
+    if (cl_info.cp_patches() != NULL) {
+      k->constants()->patch_resolved_references(cl_info.cp_patches());
     }
 
     // If it's anonymous, initialize it now, since nobody else will.
+    if (is_unsafe_anon_class) {
     k->eager_initialize(CHECK_NULL);
+    }
 
     // notify jvmti
     if (JvmtiExport::should_post_class_load()) {
         assert(THREAD->is_Java_thread(), "thread->is_Java_thread()");
         JvmtiExport::post_class_load((JavaThread *) THREAD, k);
     }
     if (class_load_start_event.should_commit()) {
       post_class_load_event(&class_load_start_event, k, loader_data);
     }
   }
-  assert(unsafe_anonymous_host != NULL || NULL == cp_patches,
+  assert(is_unsafe_anon_class || NULL == cl_info.cp_patches(),
          "cp_patches only found with unsafe_anonymous_host");
 
   return k;
 }
 

@@ -1105,17 +1160,12 @@
 
   if (k == NULL) {
     if (st->buffer() == NULL) {
       return NULL;
     }
-    k = KlassFactory::create_from_stream(st,
-                                         class_name,
-                                         loader_data,
-                                         protection_domain,
-                                         NULL, // unsafe_anonymous_host
-                                         NULL, // cp_patches
-                                         CHECK_NULL);
+    ClassLoadInfo cl_info(protection_domain);
+    k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, CHECK_NULL);
   }
 
   assert(k != NULL, "no klass created");
   Symbol* h_name = k->name();
   assert(class_name == NULL || class_name == h_name, "name mismatch");

@@ -2323,10 +2373,46 @@
       return NULL;
     }
   }
 }
 
+// Add an entry to resolution error table to record an error in resolving or
+// validating a nest host. This is used to construct informative error
+// messages when IllegalAccessError's occur. If an entry already exists it will
+// be updated with the nest host error message.
+void SystemDictionary::add_nest_host_error(const constantPoolHandle& pool,
+                                           int which,
+                                           const char* message) {
+  unsigned int hash = resolution_errors()->compute_hash(pool, which);
+  int index = resolution_errors()->hash_to_index(hash);
+  {
+    MutexLocker ml(Thread::current(), SystemDictionary_lock);
+    ResolutionErrorEntry* entry = resolution_errors()->find_entry(index, hash, pool, which);
+    if (entry != NULL) {
+      assert(entry->nest_host_error() == NULL, "Nest host error message already set!");
+      entry->set_nest_host_error(message);
+    } else {
+      resolution_errors()->add_entry(index, hash, pool, which, message);
+    }
+  }
+}
+
+// Lookup any nest host error
+const char* SystemDictionary::find_nest_host_error(const constantPoolHandle& pool, int which) {
+  unsigned int hash = resolution_errors()->compute_hash(pool, which);
+  int index = resolution_errors()->hash_to_index(hash);
+  {
+    MutexLocker ml(Thread::current(), SystemDictionary_lock);
+    ResolutionErrorEntry* entry = resolution_errors()->find_entry(index, hash, pool, which);
+    if (entry != NULL) {
+      return entry->nest_host_error();
+    } else {
+      return NULL;
+    }
+  }
+}
+
 
 // Signature constraints ensure that callers and callees agree about
 // the meaning of type names in their signatures.  This routine is the
 // intake for constraints.  It collects them from several places:
 //
< prev index next >