< prev index next >

src/hotspot/share/classfile/systemDictionary.cpp

Print this page
rev 49271 : 8199852: Print more information about class loaders in LinkageErrors.

@@ -2140,32 +2140,38 @@
 // if defining is true, then LinkageError if already in dictionary
 // if initiating loader, then ok if InstanceKlass matches existing entry
 
 void SystemDictionary::check_constraints(unsigned int d_hash,
                                          InstanceKlass* k,
-                                         Handle class_loader, bool defining,
+                                         Handle class_loader,
+                                         bool defining,
                                          TRAPS) {
   const char *linkage_error1 = NULL;
   const char *linkage_error2 = NULL;
+  const char *linkage_error3 = "";
+  // Remember the loader of the similar class that is already loaded.
+  const char *existing_klass_loader_name = "";
+
   {
     Symbol*  name  = k->name();
     ClassLoaderData *loader_data = class_loader_data(class_loader);
 
     MutexLocker mu(SystemDictionary_lock, THREAD);
 
     InstanceKlass* check = find_class(d_hash, name, loader_data->dictionary());
     if (check != NULL) {
-      // if different InstanceKlass - duplicate class definition,
-      // else - ok, class loaded by a different thread in parallel,
-      // we should only have found it if it was done loading and ok to use
-      // dictionary only holds instance classes, placeholders
-      // also holds array classes
+      // If different InstanceKlass - duplicate class definition,
+      // else - ok, class loaded by a different thread in parallel.
+      // We should only have found it if it was done loading and ok to use.
+      // The dictionary only holds instance classes, placeholders
+      // also hold array classes.
 
       assert(check->is_instance_klass(), "noninstance in systemdictionary");
       if ((defining == true) || (k != check)) {
-        linkage_error1 = "loader (instance of ";
-        linkage_error2 = "): attempted duplicate class definition for name: \"";
+        linkage_error1 = "loader ";
+        linkage_error2 = " attempted duplicate class definition for ";
+        guarantee(check->class_loader() == class_loader(), "Per construction. Else report the other loader.");
       } else {
         return;
       }
     }
 

@@ -2174,32 +2180,39 @@
     assert(ph_check == NULL || ph_check == name, "invalid symbol");
 #endif
 
     if (linkage_error1 == NULL) {
       if (constraints()->check_or_update(k, class_loader, name) == false) {
-        linkage_error1 = "loader constraint violation: loader (instance of ";
-        linkage_error2 = ") previously initiated loading for a different type with name \"";
+        linkage_error1 = "loader constraint violation: loader ";
+        linkage_error2 = " wants to load class ";
+        linkage_error3 = ". A different class with the same name was previously loaded by ";
+        Klass *existing_klass = constraints()->find_constrained_klass(name, class_loader);
+        if (existing_klass->class_loader() != class_loader()) {
+          existing_klass_loader_name =
+            java_lang_ClassLoader::describe_external(existing_klass->class_loader());
+        }
       }
     }
   }
 
   // Throw error now if needed (cannot throw while holding
   // SystemDictionary_lock because of rank ordering)
 
   if (linkage_error1) {
     ResourceMark rm(THREAD);
-    const char* class_loader_name = loader_name(class_loader());
-    char* type_name = k->name()->as_C_string();
-    size_t buflen = strlen(linkage_error1) + strlen(class_loader_name) +
-      strlen(linkage_error2) + strlen(type_name) + 2; // +2 for '"' and null byte.
-    char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
-    jio_snprintf(buf, buflen, "%s%s%s%s\"", linkage_error1, class_loader_name, linkage_error2, type_name);
-    THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
+    stringStream ss;
+    ss.print("%s", linkage_error1);
+    ss.print("%s", java_lang_ClassLoader::describe_external(class_loader()));
+    ss.print("%s", linkage_error2);
+    ss.print("%s", k->external_name());
+    ss.print("%s", linkage_error3);
+    ss.print("%s", existing_klass_loader_name);
+    ss.print(".");
+    THROW_MSG(vmSymbols::java_lang_LinkageError(), ss.as_string());
   }
 }
 
-
 // Update class loader data dictionary - done after check_constraint and add_to_hierachy
 // have been called.
 void SystemDictionary::update_dictionary(unsigned int d_hash,
                                          int p_index, unsigned int p_hash,
                                          InstanceKlass* k,

@@ -3091,14 +3104,22 @@
   _loader_constraints  = new LoaderConstraintTable(_loader_constraint_size);
 
   NOT_PRODUCT(SystemDictionary::verify());
 }
 
-// caller needs ResourceMark
+// Return string to give helpful intformation about a classloader.
+// Caller needs ResourceMark.
 const char* SystemDictionary::loader_name(const oop loader) {
-  return ((loader) == NULL ? "<bootloader>" :
-          InstanceKlass::cast((loader)->klass())->name()->as_C_string());
+#if INCLUDE_CDS
+  if (DumpSharedSpaces) {
+    // Describe_external() calls assert(is_instance...) in various places,
+    // which may fail with DumpSharedSpaces.
+    if ((loader) == NULL) return "<bootloader>";
+    return InstanceKlass::cast((loader)->klass())->name()->as_C_string();
+  }
+#endif
+  return java_lang_ClassLoader::describe_external(loader);
 }
 
 // caller needs ResourceMark
 const char* SystemDictionary::loader_name(const ClassLoaderData* loader_data) {
   return (loader_data->class_loader() == NULL ? "<bootloader>" :
< prev index next >