< prev index next >
src/hotspot/share/classfile/systemDictionary.cpp
Print this page
rev 49271 : 8199852: Print more information about class loaders in LinkageErrors.
*** 2140,2171 ****
// 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,
TRAPS) {
const char *linkage_error1 = NULL;
const char *linkage_error2 = NULL;
{
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
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: \"";
} else {
return;
}
}
--- 2140,2177 ----
// 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,
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.
! // 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 ";
! linkage_error2 = " attempted duplicate class definition for ";
! guarantee(check->class_loader() == class_loader(), "Per construction. Else report the other loader.");
} else {
return;
}
}
*** 2174,2205 ****
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 \"";
}
}
}
// 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);
}
}
-
// 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,
--- 2180,2218 ----
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 ";
! 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);
! 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,3104 ****
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
NOT_PRODUCT(SystemDictionary::verify());
}
! // caller needs ResourceMark
const char* SystemDictionary::loader_name(const oop loader) {
! return ((loader) == NULL ? "<bootloader>" :
! InstanceKlass::cast((loader)->klass())->name()->as_C_string());
}
// caller needs ResourceMark
const char* SystemDictionary::loader_name(const ClassLoaderData* loader_data) {
return (loader_data->class_loader() == NULL ? "<bootloader>" :
--- 3104,3125 ----
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
NOT_PRODUCT(SystemDictionary::verify());
}
! // Return string to give helpful intformation about a classloader.
! // Caller needs ResourceMark.
const char* SystemDictionary::loader_name(const oop loader) {
! #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 >