src/share/vm/classfile/systemDictionary.cpp

Print this page

        

@@ -138,28 +138,10 @@
   if (class_loader() == NULL) return ClassLoaderData::the_null_class_loader_data();
   return ClassLoaderDataGraph::find_or_create(class_loader, THREAD);
 }
 
 // ----------------------------------------------------------------------------
-// debugging
-
-#ifdef ASSERT
-
-// return true if class_name contains no '.' (internal format is '/')
-bool SystemDictionary::is_internal_format(Symbol* class_name) {
-  if (class_name != NULL) {
-    ResourceMark rm;
-    char* name = class_name->as_C_string();
-    return strchr(name, '.') == NULL;
-  } else {
-    return true;
-  }
-}
-
-#endif
-
-// ----------------------------------------------------------------------------
 // Parallel class loading check
 
 bool SystemDictionary::is_parallelCapable(Handle class_loader) {
   if (UnsyncloadClass || class_loader.is_null()) return true;
   if (AlwaysLockClassLoader) return false;

@@ -349,10 +331,12 @@
     if (k) {
       return k;
     }
   }
 #endif // INCLUDE_CDS
+  // leave PENDING_EXCEPTION handling in this code to ensure we do the placeholder cleanup (find_and_remove)
+  // and do not throw exceptions while holding locks
 
   // Double-check, if child class is already loaded, just return super-class,interface
   // Don't add a placedholder if already loaded, i.e. already in system dictionary
   // Make sure there's a placeholder for the *child* before resolving.
   // Used as a claim that this thread is currently loading superclass/classloader

@@ -653,10 +637,12 @@
     event.commit();
   }
 #endif // INCLUDE_TRACE
 }
 
+// leave PENDING_EXCEPTION handling in this code to ensure we do the placeholder cleanup (find_and_remove)
+// and do not throw exceptions while holding locks
 Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
                                                         Handle class_loader,
                                                         Handle protection_domain,
                                                         TRAPS) {
   assert(name != NULL && !FieldType::is_array(name) &&

@@ -1013,13 +999,39 @@
     k = find(class_name, class_loader, protection_domain, THREAD);
   }
   return k;
 }
 
+// Only boot and platform class loaders can define classes in "java/" packages.
+void SystemDictionary::check_prohibited_package(Symbol* class_name,
+                                                Handle class_loader,
+                                                TRAPS) {
+  const char* javapkg = "java/";
+  ResourceMark rm(THREAD);
+  if (!class_loader.is_null() &&
+      !SystemDictionary::is_platform_class_loader(class_loader) &&
+      class_name != NULL &&
+      strncmp(class_name->as_C_string(), javapkg, strlen(javapkg)) == 0) {
+    TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK);
+    assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'");
+    char* name = pkg_name->as_C_string();
+    const char* class_loader_name = loader_name(class_loader());
+    StringUtils::replace_no_expand(name, "/", ".");
+    const char* msg_text1 = "Class loader (instance of): ";
+    const char* msg_text2 = " tried to load prohibited package name: ";
+    size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(name) + 1;
+    char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
+    jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, name);
+    THROW_MSG(vmSymbols::java_lang_SecurityException(), message);
+  }
+  return;
+}
+
 // Note: this method is much like resolve_from_stream, but
-// updates no supplemental data structures.
-// TODO consolidate the two methods with a helper routine?
+// does not publish the classes via the SystemDictionary.
+// Handles unsafe_DefineAnonymousClass and redefineclasses
+// redefinedclasses do not add to the class hierarchy
 Klass* SystemDictionary::parse_stream(Symbol* class_name,
                                       Handle class_loader,
                                       Handle protection_domain,
                                       ClassFileStream* st,
                                       const Klass* host_klass,

@@ -1052,12 +1064,12 @@
                                                            class_name,
                                                            loader_data,
                                                            protection_domain,
                                                            host_klass,
                                                            cp_patches,
-                                                           NULL, // parsed_name
-                                                           THREAD);
+                                                           CHECK_NULL);
+
 
   if (host_klass != NULL && k.not_null()) {
     // If it's anonymous, initialize it now, since nobody else will.
 
     {

@@ -1092,10 +1104,11 @@
          "cp_patches only found with host_klass");
 
   return k();
 }
 
+
 // Add a klass to the system from a stream (called by jni_DefineClass and
 // JVM_DefineClass).
 // Note: class_name can be NULL. In that case we do not know the name of
 // the class until we have parsed the stream.
 

@@ -1124,12 +1137,10 @@
   // Parse the stream and create a klass.
   // Note that we do this even though this klass might
   // already be present in the SystemDictionary, otherwise we would not
   // throw potential ClassFormatErrors.
   //
-  // Note: "parsed_name" is updated.
-  TempNewSymbol parsed_name = NULL;
 
  instanceKlassHandle k;
 
 #if INCLUDE_CDS
   k = SystemDictionaryShared::lookup_from_stream(class_name,

@@ -1137,80 +1148,42 @@
                                                  protection_domain,
                                                  st,
                                                  CHECK_NULL);
 #endif
 
-  if (k.not_null()) {
-    parsed_name = k->name();
-  } else {
+  if (k.is_null()) {
     if (st->buffer() == NULL) {
       return NULL;
     }
     k = KlassFactory::create_from_stream(st,
                                          class_name,
                                          loader_data,
                                          protection_domain,
                                          NULL, // host_klass
                                          NULL, // cp_patches
-                                         &parsed_name,
-                                         THREAD);
-  }
-
-  const char* pkg = "java/";
-  if (!HAS_PENDING_EXCEPTION &&
-      !class_loader.is_null() &&
-      !SystemDictionary::is_platform_class_loader(class_loader) &&
-      parsed_name != NULL &&
-      !strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) {
-    // It is illegal to define classes in the "java." package from
-    // JVM_DefineClass or jni_DefineClass unless you're the bootclassloader
-    ResourceMark rm(THREAD);
-    TempNewSymbol pkg_name = InstanceKlass::package_from_name(parsed_name, CHECK_NULL);
-    assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'");
-    char* name = pkg_name->as_C_string();
-    StringUtils::replace_no_expand(name, "/", ".");
-    const char* msg_text = "Prohibited package name: ";
-    size_t len = strlen(msg_text) + strlen(name) + 1;
-    char* message = NEW_RESOURCE_ARRAY(char, len);
-    jio_snprintf(message, len, "%s%s", msg_text, name);
-    Exceptions::_throw_msg(THREAD_AND_LOCATION,
-      vmSymbols::java_lang_SecurityException(), message);
+                                         CHECK_NULL);
   }
 
-  if (!HAS_PENDING_EXCEPTION) {
-    assert(parsed_name != NULL, "Sanity");
-    assert(class_name == NULL || class_name == parsed_name, "name mismatch");
-    // Verification prevents us from creating names with dots in them, this
-    // asserts that that's the case.
-    assert(is_internal_format(parsed_name),
-           "external class name format used internally");
+  assert(k.not_null(), "no klass created");
+  Symbol* h_name = k->name();
+  assert(class_name == NULL || class_name == h_name, "name mismatch");
 
     // Add class just loaded
     // If a class loader supports parallel classloading handle parallel define requests
     // find_or_define_instance_class may return a different InstanceKlass
     if (is_parallelCapable(class_loader)) {
-      k = find_or_define_instance_class(class_name, class_loader, k, THREAD);
+    k = find_or_define_instance_class(h_name, class_loader, k, CHECK_NULL);
     } else {
-      define_instance_class(k, THREAD);
-    }
+    define_instance_class(k, CHECK_NULL);
   }
 
   // Make sure we have an entry in the SystemDictionary on success
   debug_only( {
-    if (!HAS_PENDING_EXCEPTION) {
-      assert(parsed_name != NULL, "parsed_name is still null?");
-      Symbol*  h_name    = k->name();
-      ClassLoaderData *defining_loader_data = k->class_loader_data();
-
       MutexLocker mu(SystemDictionary_lock, THREAD);
 
-      Klass* check = find_class(parsed_name, loader_data);
+    Klass* check = find_class(h_name, k->class_loader_data());
       assert(check == k(), "should be present in the dictionary");
-
-      Klass* check2 = find_class(h_name, defining_loader_data);
-      assert(check == check2, "name inconsistancy in SystemDictionary");
-    }
   } );
 
   return k();
 }
 

@@ -1398,10 +1371,12 @@
     ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
     {
       Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
       check_loader_lock_contention(lockObject, THREAD);
       ObjectLocker ol(lockObject, THREAD, true);
+      // prohibited package check assumes all classes loaded from archive call
+      // restore_unshareable_info which calls ik->set_package()
       ik->restore_unshareable_info(loader_data, protection_domain, CHECK_(nh));
     }
 
     if (log_is_enabled(Info, class, load)) {
       ik()->print_loading_log(LogLevel::Info, loader_data, NULL, NULL);

@@ -1418,10 +1393,11 @@
       int path_index = ik->shared_classpath_index();
       ResourceMark rm;
       ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
     }
 
+
     if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
       // Only dump the classes that can be stored into CDS archive
       if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
         ResourceMark rm(THREAD);
         classlist_file->print_cr("%s", ik->name()->as_C_string());

@@ -1684,10 +1660,12 @@
 // False is the requested default.
 // For better performance, the class loaders should synchronize
 // findClass(), i.e. FindLoadedClass/DefineClassIfAbsent or they
 // potentially waste time reading and parsing the bytestream.
 // Note: VM callers should ensure consistency of k/class_name,class_loader
+// leave PENDING_EXCEPTION handling in this code to ensure we do the placeholder cleanup (find_and_remove)
+// and do not throw exceptions while holding locks
 instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* class_name, Handle class_loader, instanceKlassHandle k, TRAPS) {
 
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
   Symbol*  name_h = k->name(); // passed in class_name may be null
   ClassLoaderData* loader_data = class_loader_data(class_loader);