--- old/src/hotspot/share/classfile/classLoaderData.cpp 2018-06-13 19:36:12.872023919 -0400 +++ new/src/hotspot/share/classfile/classLoaderData.cpp 2018-06-13 19:36:10.945545395 -0400 @@ -109,7 +109,7 @@ // class_loader oop is no longer alive, during unloading. void ClassLoaderData::initialize_name_and_klass(Handle class_loader) { _class_loader_klass = class_loader->klass(); - oop class_loader_name = java_lang_ClassLoader::name(class_loader()); + oop class_loader_name = java_lang_ClassLoader::nameAndId(class_loader()); if (class_loader_name != NULL) { Thread* THREAD = Thread::current(); ResourceMark rm(THREAD); @@ -118,9 +118,16 @@ if (class_loader_instance_name != NULL && class_loader_instance_name[0] != '\0') { // Can't throw InternalError and SymbolTable doesn't throw OOM anymore. - _class_loader_name = SymbolTable::new_symbol(class_loader_instance_name, CATCH); + _class_loader_name_id = SymbolTable::new_symbol(class_loader_instance_name, CATCH); } } + + // The class loader's nameAndId should be set in ClassLoader's constructor. + // If for some reason the constructor is not run, instead of leaving the name set + // to null, fallback to the . + if (_class_loader_name_id == NULL) { + _class_loader_name_id = _class_loader_klass->name(); + } } ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) : @@ -134,7 +141,7 @@ _claimed(0), _modified_oops(true), _accumulated_modified_oops(false), _jmethod_ids(NULL), _handles(), _deallocate_list(NULL), _next(NULL), - _class_loader_klass(NULL), _class_loader_name(NULL), + _class_loader_klass(NULL), _class_loader_name_id(NULL), _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true, Monitor::_safepoint_check_never)) { @@ -911,28 +918,25 @@ return ClassLoaderDataGraph::add(loader, true); } +// Caller needs ResourceMark +// If the defining loader has a name explicitly set then '' @ +// If the defining loader has no name then @ +// If built-in loader, then omit '@' as there is only one instance. const char* ClassLoaderData::loader_name() const { - if (is_unloading()) { - if (_class_loader_klass == NULL) { - return ""; - } else if (_class_loader_name != NULL) { - return _class_loader_name->as_C_string(); - } else { - return _class_loader_klass->name()->as_C_string(); - } + if (_class_loader_klass == NULL) { + return "'bootstrap'"; } else { - // Handles null class loader - return SystemDictionary::loader_name(class_loader()); + assert(_class_loader_name_id != NULL, "encountered a null class loader name"); + return _class_loader_name_id->as_C_string(); } } - void ClassLoaderData::print_value_on(outputStream* out) const { if (!is_unloading() && class_loader() != NULL) { out->print("loader data: " INTPTR_FORMAT " for instance ", p2i(this)); class_loader()->print_value_on(out); // includes loader_name() and address of class loader instance } else { - // loader data: 0xsomeaddr of + // loader data: 0xsomeaddr of 'bootstrap' out->print("loader data: " INTPTR_FORMAT " of %s", p2i(this), loader_name()); } if (is_anonymous()) { @@ -1237,7 +1241,7 @@ FOR_ALL_DICTIONARY(cld) { ResourceMark rm; stringStream tempst; - tempst.print("System Dictionary for %s", cld->loader_name()); + tempst.print("System Dictionary for %s class loader", cld->loader_name()); cld->dictionary()->print_table_statistics(st, tempst.as_string()); } } --- old/src/hotspot/share/classfile/classLoaderData.hpp 2018-06-13 19:36:24.648836269 -0400 +++ new/src/hotspot/share/classfile/classLoaderData.hpp 2018-06-13 19:36:23.047726584 -0400 @@ -260,7 +260,7 @@ // JFR support Klass* _class_loader_klass; - Symbol* _class_loader_name; + Symbol* _class_loader_name_id; JFR_ONLY(DEFINE_TRACE_ID_FIELD;) void set_next(ClassLoaderData* next) { _next = next; } @@ -362,8 +362,6 @@ void initialize_holder(Handle holder); - inline unsigned int identity_hash() const { return (unsigned int)(((intptr_t)this) >> 3); } - void oops_do(OopClosure* f, bool must_claim, bool clear_modified_oops = false); void classes_do(KlassClosure* klass_closure); @@ -377,7 +375,6 @@ void print_value() { print_value_on(tty); } void print_value_on(outputStream* out) const; void verify(); - const char* loader_name() const; OopHandle add_handle(Handle h); void remove_handle(OopHandle h); @@ -404,11 +401,10 @@ // Also works if unloading. Klass* class_loader_klass() const { return _class_loader_klass; } - // Returns Name of associated class loader. - // Returns NULL if associated class loader is or if no name has been set for - // this loader. - // Also works if unloading. - Symbol* class_loader_name() const { return _class_loader_name; } + // Both methods return the class loader's nameAndId in char* or Symbol* format. + // Both methods work during unloading. + const char* loader_name() const; + Symbol* class_loader_name() const { return _class_loader_name_id; } JFR_ONLY(DEFINE_TRACE_ID_METHODS;) }; --- old/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp 2018-06-13 19:36:35.993729363 -0400 +++ new/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp 2018-06-13 19:36:34.498091592 -0400 @@ -156,18 +156,14 @@ // Retrieve information. const Klass* const loader_klass = _cld->class_loader_klass(); - const Symbol* const loader_name = _cld->class_loader_name(); + const char* const loader_name = _cld->loader_name(); branchtracker.print(st); // e.g. "+--- jdk.internal.reflect.DelegatingClassLoader" st->print("+%.*s", BranchTracker::twig_len, "----------"); - if (_cld->is_the_null_class_loader_data()) { - st->print(" "); - } else { - if (loader_name != NULL) { - st->print(" \"%s\",", loader_name->as_C_string()); - } + st->print(" \"%s\",", loader_name); + if (!_cld->is_the_null_class_loader_data()) { st->print(" %s", loader_klass != NULL ? loader_klass->external_name() : "??"); st->print(" {" PTR_FORMAT "}", p2i(_loader_oop)); } --- old/src/hotspot/share/classfile/dictionary.cpp 2018-06-13 19:36:48.271347134 -0400 +++ new/src/hotspot/share/classfile/dictionary.cpp 2018-06-13 19:36:46.911630329 -0400 @@ -641,6 +641,6 @@ ResourceMark rm; stringStream tempst; - tempst.print("System Dictionary for %s", cld->loader_name()); + tempst.print("System Dictionary for %s class loader", cld->loader_name()); verify_table(tempst.as_string()); } --- old/src/hotspot/share/classfile/javaClasses.cpp 2018-06-13 19:36:59.950143961 -0400 +++ new/src/hotspot/share/classfile/javaClasses.cpp 2018-06-13 19:36:58.455675555 -0400 @@ -3993,6 +3993,7 @@ int java_lang_ClassLoader::_loader_data_offset = -1; int java_lang_ClassLoader::parallelCapable_offset = -1; int java_lang_ClassLoader::name_offset = -1; +int java_lang_ClassLoader::nameAndId_offset = -1; int java_lang_ClassLoader::unnamedModule_offset = -1; ClassLoaderData* java_lang_ClassLoader::loader_data(oop loader) { @@ -4008,6 +4009,7 @@ #define CLASSLOADER_FIELDS_DO(macro) \ macro(parallelCapable_offset, k1, "parallelLockMap", concurrenthashmap_signature, false); \ macro(name_offset, k1, vmSymbols::name_name(), string_signature, false); \ + macro(nameAndId_offset, k1, "nameAndId", string_signature, false); \ macro(unnamedModule_offset, k1, "unnamedModule", module_signature, false); \ macro(parent_offset, k1, "parent", classloader_signature, false) @@ -4033,11 +4035,20 @@ return loader->obj_field(parent_offset); } +// Returns the name of this class loader or null if this class loader is not named. oop java_lang_ClassLoader::name(oop loader) { assert(is_instance(loader), "loader must be oop"); return loader->obj_field(name_offset); } +// If the defining loader has a name explicitly set then '' @ +// If the defining loader has no name then @ +// If built-in loader, then omit '@' as there is only one instance. +oop java_lang_ClassLoader::nameAndId(oop loader) { + assert(is_instance(loader), "loader must be oop"); + return loader->obj_field(nameAndId_offset); +} + bool java_lang_ClassLoader::isAncestor(oop loader, oop cl) { assert(is_instance(loader), "loader must be oop"); assert(cl == NULL || is_instance(cl), "cl argument must be oop"); @@ -4111,39 +4122,28 @@ // Caller needs ResourceMark. const char* java_lang_ClassLoader::describe_external(const oop loader) { + ClassLoaderData *cld = ClassLoaderData::class_loader_data(loader); + const char* name = cld->loader_name(); + + // bootstrap loader if (loader == NULL) { - return ""; + return name; } bool well_known_loader = SystemDictionary::is_system_class_loader(loader) || SystemDictionary::is_platform_class_loader(loader); - const char* name = NULL; - oop nameOop = java_lang_ClassLoader::name(loader); - if (nameOop != NULL) { - name = java_lang_String::as_utf8_string(nameOop); - } - if (name == NULL) { - // Use placeholder for missing name to have fixed message format. - name = ""; - } - stringStream ss; - ss.print("\"%s\" (instance of %s", name, loader->klass()->external_name()); + ss.print("%s (instance of %s", name, loader->klass()->external_name()); if (!well_known_loader) { - const char* parentName = NULL; oop pl = java_lang_ClassLoader::parent(loader); + ClassLoaderData *pl_cld = ClassLoaderData::class_loader_data(pl); + const char* parentName = pl_cld->loader_name(); if (pl != NULL) { - oop parentNameOop = java_lang_ClassLoader::name(pl); - if (parentNameOop != NULL) { - parentName = java_lang_String::as_utf8_string(parentNameOop); - } - if (parentName == NULL) { - parentName = ""; - } - ss.print(", child of \"%s\" %s", parentName, pl->klass()->external_name()); + ss.print(", child of %s %s", parentName, pl->klass()->external_name()); } else { - ss.print(", child of "); + // bootstrap loader + ss.print(", child of %s", parentName); } } ss.print(")"); --- old/src/hotspot/share/classfile/javaClasses.hpp 2018-06-13 19:37:11.757737939 -0400 +++ new/src/hotspot/share/classfile/javaClasses.hpp 2018-06-13 19:37:10.315876629 -0400 @@ -1272,6 +1272,7 @@ static int parent_offset; static int parallelCapable_offset; static int name_offset; + static int nameAndId_offset; static int unnamedModule_offset; public: @@ -1283,6 +1284,7 @@ static oop parent(oop loader); static oop name(oop loader); + static oop nameAndId(oop loader); static bool isAncestor(oop loader, oop cl); // Support for parallelCapable field --- old/src/hotspot/share/classfile/loaderConstraints.cpp 2018-06-13 19:37:23.248054754 -0400 +++ new/src/hotspot/share/classfile/loaderConstraints.cpp 2018-06-13 19:37:21.894719702 -0400 @@ -177,8 +177,8 @@ lt.print("Failed to add constraint for name: %s, loader[0]: %s," " loader[1]: %s, Reason: %s", class_name->as_C_string(), - SystemDictionary::loader_name(class_loader1()), - SystemDictionary::loader_name(class_loader2()), + ClassLoaderData::class_loader_data(class_loader1())->loader_name(), + ClassLoaderData::class_loader_data(class_loader2())->loader_name(), reason); } } @@ -247,8 +247,8 @@ lt.print("adding new constraint for name: %s, loader[0]: %s," " loader[1]: %s", class_name->as_C_string(), - SystemDictionary::loader_name(class_loader1()), - SystemDictionary::loader_name(class_loader2()) + ClassLoaderData::class_loader_data(class_loader1())->loader_name(), + ClassLoaderData::class_loader_data(class_loader2())->loader_name() ); } } else if (*pp1 == *pp2) { @@ -260,7 +260,7 @@ lt.print("setting class object in existing constraint for" " name: %s and loader %s", class_name->as_C_string(), - SystemDictionary::loader_name(class_loader1()) + ClassLoaderData::class_loader_data(class_loader1())->loader_name() ); } } else { @@ -291,7 +291,7 @@ lt.print("constraint check failed for name %s, loader %s: " "the presented class object differs from that stored", name->as_C_string(), - SystemDictionary::loader_name(loader())); + ClassLoaderData::class_loader_data(loader())->loader_name()); } return false; } else { @@ -302,7 +302,7 @@ lt.print("updating constraint for name %s, loader %s, " "by setting class object", name->as_C_string(), - SystemDictionary::loader_name(loader())); + ClassLoaderData::class_loader_data(loader())->loader_name()); } } return true; @@ -353,7 +353,7 @@ lt.print("extending constraint for name %s by adding loader[%d]: %s %s", p->name()->as_C_string(), num, - SystemDictionary::loader_name(loader()), + ClassLoaderData::class_loader_data(loader())->loader_name(), (p->klass() == NULL ? " and setting class object" : "") ); } --- old/src/hotspot/share/classfile/modules.cpp 2018-06-13 19:37:34.961533506 -0400 +++ new/src/hotspot/share/classfile/modules.cpp 2018-06-13 19:37:33.607832934 -0400 @@ -312,6 +312,10 @@ "Class loader is an invalid delegating class loader"); } Handle h_loader = Handle(THREAD, loader); + // define_module can be called during start-up, before the class loader's ClassLoaderData + // has been created. SystemDictionary::register_loader ensures creation, if needed. + ClassLoaderData* loader_data = SystemDictionary::register_loader(h_loader); + assert(loader_data != NULL, "class loader data shouldn't be null"); // Check that the list of packages has no duplicates and that the // packages are syntactically ok. @@ -329,7 +333,7 @@ !SystemDictionary::is_platform_class_loader(h_loader()) && (strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0 && (package_name[JAVAPKG_LEN] == '/' || package_name[JAVAPKG_LEN] == '\0'))) { - const char* class_loader_name = SystemDictionary::loader_name(h_loader()); + const char* class_loader_name = loader_data->loader_name(); size_t pkg_len = strlen(package_name); char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len); strncpy(pkg_name, package_name, pkg_len); @@ -373,9 +377,6 @@ } } - ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(h_loader()); - assert(loader_data != NULL, "class loader data shouldn't be null"); - PackageEntryTable* package_table = NULL; PackageEntry* existing_pkg = NULL; { --- old/src/hotspot/share/classfile/systemDictionary.cpp 2018-06-13 19:37:47.410408511 -0400 +++ new/src/hotspot/share/classfile/systemDictionary.cpp 2018-06-13 19:37:45.911994143 -0400 @@ -3012,18 +3012,6 @@ NOT_PRODUCT(SystemDictionary::verify()); } -// caller needs ResourceMark -const char* SystemDictionary::loader_name(const oop loader) { - return ((loader) == NULL ? "" : - 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 ? "" : - SystemDictionary::loader_name(loader_data->class_loader())); -} - void SystemDictionary::initialize_oop_storage() { _vm_weak_oop_storage = new OopStorage("VM Weak Oop Handles", --- old/src/hotspot/share/classfile/systemDictionary.hpp 2018-06-13 19:37:59.011334857 -0400 +++ new/src/hotspot/share/classfile/systemDictionary.hpp 2018-06-13 19:37:57.612982267 -0400 @@ -570,10 +570,6 @@ Handle *method_type_result, TRAPS); - // Utility for printing loader "name" as part of tracing constraints - static const char* loader_name(const oop loader); - static const char* loader_name(const ClassLoaderData* loader_data); - // Record the error when the first attempt to resolve a reference from a constant // pool entry to a class fails. static void add_resolution_error(const constantPoolHandle& pool, int which, Symbol* error, --- old/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp 2018-06-13 19:38:12.074475299 -0400 +++ new/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp 2018-06-13 19:38:10.630748216 -0400 @@ -295,8 +295,8 @@ bool has_cstring_entries() const { return _cstring_table->has_entries(); } }; -// external name (synthetic) for the primordial "boot" class loader instance -const char* const boot_class_loader_name = "boot"; +// external name (synthetic) for the primordial "'bootstrap'" class loader instance +const char* const boot_class_loader_name = "'bootstrap'"; /** * When processing a set of artifacts, there will be a need --- old/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp 2018-06-13 19:38:24.064593434 -0400 +++ new/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp 2018-06-13 19:38:22.645450611 -0400 @@ -86,14 +86,9 @@ // Note: this should also work if unloading: Klass* k = cld->class_loader_klass(); + name = cld->loader_name(); if (k != NULL) { class_name = k->external_name(); - Symbol* s = cld->class_loader_name(); - if (s != NULL) { - name = s->as_C_string(); - } - } else { - name = ""; } // Print --- old/src/hotspot/share/oops/instanceKlass.cpp 2018-06-13 19:38:36.193695722 -0400 +++ new/src/hotspot/share/oops/instanceKlass.cpp 2018-06-13 19:38:34.540517112 -0400 @@ -2328,8 +2328,7 @@ void InstanceKlass::set_package(ClassLoaderData* loader_data, TRAPS) { // ensure java/ packages only loaded by boot or platform builtin loaders - Handle class_loader(THREAD, loader_data->class_loader()); - check_prohibited_package(name(), class_loader, CHECK); + check_prohibited_package(name(), loader_data, CHECK); TempNewSymbol pkg_name = package_from_name(name(), CHECK); @@ -2471,10 +2470,10 @@ // Only boot and platform class loaders can define classes in "java/" packages. void InstanceKlass::check_prohibited_package(Symbol* class_name, - Handle class_loader, + ClassLoaderData* loader_data, TRAPS) { - if (!class_loader.is_null() && - !SystemDictionary::is_platform_class_loader(class_loader()) && + if (!loader_data->is_boot_class_loader_data() && + !loader_data->is_platform_class_loader_data() && class_name != NULL) { ResourceMark rm(THREAD); char* name = class_name->as_C_string(); @@ -2482,7 +2481,7 @@ TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK); assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'"); name = pkg_name->as_C_string(); - const char* class_loader_name = SystemDictionary::loader_name(class_loader()); + const char* class_loader_name = loader_data->loader_name(); StringUtils::replace_no_expand(name, "/", "."); const char* msg_text1 = "Class loader (instance of): "; const char* msg_text2 = " tried to load prohibited package name: "; --- old/src/hotspot/share/oops/instanceKlass.hpp 2018-06-13 19:38:48.671201067 -0400 +++ new/src/hotspot/share/oops/instanceKlass.hpp 2018-06-13 19:38:47.270789153 -0400 @@ -471,7 +471,7 @@ private: // Check prohibited package ("java/" only loadable by boot or platform loaders) static void check_prohibited_package(Symbol* class_name, - Handle class_loader, + ClassLoaderData* loader_data, TRAPS); public: // tell if two classes have the same enclosing class (at package level) --- old/src/java.base/share/classes/java/lang/ClassLoader.java 2018-06-13 19:39:02.309698341 -0400 +++ new/src/java.base/share/classes/java/lang/ClassLoader.java 2018-06-13 19:39:00.729038491 -0400 @@ -59,6 +59,7 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; +import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.perf.PerfCounter; import jdk.internal.loader.BootLoader; import jdk.internal.loader.ClassLoaders; @@ -246,6 +247,9 @@ // the unnamed module for this ClassLoader private final Module unnamedModule; + // a string for exception message printing + private final String nameAndId; + /** * Encapsulates the set of parallel capable loader types. */ @@ -381,6 +385,24 @@ package2certs = new Hashtable<>(); assertionLock = this; } + this.nameAndId = nameAndId(this); + } + + /** + * If the defining loader has a name explicitly set then + * '' @ + * If the defining loader has no name then + * @ + * If it's built-in loader then omit `@` as there is only one instance. + */ + private static String nameAndId(ClassLoader ld) { + String nid = ld.getName() != null ? "\'" + ld.getName() + "\'" + : ld.getClass().getName(); + if (!(ld instanceof BuiltinClassLoader)) { + String id = Integer.toHexString(System.identityHashCode(ld)); + nid = nid + " @" + id; + } + return nid; } /** --- old/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/Test.java 2018-06-13 19:39:16.525190184 -0400 +++ new/test/hotspot/jtreg/runtime/LoaderConstraints/differentLE/Test.java 2018-06-13 19:39:15.081311624 -0400 @@ -75,11 +75,13 @@ // Then it loads the D2 variant of D from the current working directory and it's // superclass C. This fails as D1 is already loaded with the same superclass. - static String expectedErrorMessage = - "loader constraint violation: loader \"\" (instance of PreemptingClassLoader, " + - "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) wants to load " + + // Break the expectedErrorMessage into 2 pieces since the loader name will include + // its identity hash and can not be compared against. + static String expectedErrorMessage_part1 = "loader constraint violation: loader PreemptingClassLoader @"; + static String expectedErrorMessage_part2 = " (instance of PreemptingClassLoader, " + + "child of 'app' jdk.internal.loader.ClassLoaders$AppClassLoader) wants to load " + "class test.D_ambgs. A different class with the same name was previously loaded " + - "by \"app\" (instance of jdk.internal.loader.ClassLoaders$AppClassLoader)."; + "by 'app' (instance of jdk.internal.loader.ClassLoaders$AppClassLoader)."; public static void test_access() throws Exception { try { @@ -101,8 +103,9 @@ throw new RuntimeException("Expected LinkageError was not thrown."); } catch (LinkageError jle) { String errorMsg = jle.getMessage(); - if (!errorMsg.equals(expectedErrorMessage)) { - System.out.println("Expected: " + expectedErrorMessage + "\n" + + if (!errorMsg.contains(expectedErrorMessage_part1) || + !errorMsg.contains(expectedErrorMessage_part2)) { + System.out.println("Expected: " + expectedErrorMessage_part1 + "" + expectedErrorMessage_part2 + "\n" + "but got: " + errorMsg); throw new RuntimeException("Wrong error message of LinkageError."); } else { --- old/test/hotspot/jtreg/runtime/LoaderConstraints/duplicateLE/Test.java 2018-06-13 19:39:28.046858396 -0400 +++ new/test/hotspot/jtreg/runtime/LoaderConstraints/duplicateLE/Test.java 2018-06-13 19:39:26.646838797 -0400 @@ -37,23 +37,30 @@ // Check that all names have external formatting ('.' and not '/' in package names). // Check for parent of class loader. - static String expectedErrorMessage1 = - "loader \"\" (instance of PreemptingClassLoader, " + - "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + // Break each expectedErrorMessage into 2 parts due to the class loader name containing + // the unique @ identity hash which cannot be compared against. + static String expectedErrorMessage1_part1 = "loader PreemptingClassLoader @"; + static String expectedErrorMessage1_part2 = + " (instance of PreemptingClassLoader, " + + "child of 'app' jdk.internal.loader.ClassLoaders$AppClassLoader) " + "attempted duplicate class definition for test.Foo."; + // Check that all names have external formatting ('.' and not '/' in package names). // Check for name and parent of class loader. - static String expectedErrorMessage2 = - "loader \"DuplicateLE_Test_Loader\" (instance of PreemptingClassLoader, " + - "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + static String expectedErrorMessage2_part1 = "loader 'DuplicateLE_Test_Loader' @"; + static String expectedErrorMessage2_part2 = + " (instance of PreemptingClassLoader, " + + "child of 'app' jdk.internal.loader.ClassLoaders$AppClassLoader) " + "attempted duplicate class definition for test.Foo."; + // Check that all names have external formatting ('.' and not '/' in package names). // Check for name and parent of class loader. Type should be mentioned as 'interface'. - static String expectedErrorMessage3 = - "loader \"DuplicateLE_Test_Loader_IF\" (instance of PreemptingClassLoader, " + - "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + static String expectedErrorMessage3_part1 = "loader 'DuplicateLE_Test_Loader_IF' @"; + static String expectedErrorMessage3_part2 = + " (instance of PreemptingClassLoader, " + + "child of 'app' jdk.internal.loader.ClassLoaders$AppClassLoader) " + "attempted duplicate interface definition for test.J."; // Test that the error message is correct when a loader constraint error is @@ -63,7 +70,8 @@ // overrides "J.m()LFoo;". But, Task's class Foo and super type J's class Foo // are different. So, a LinkageError exception should be thrown because the // loader constraint check will fail. - public static void test(String loaderName, String expectedErrorMessage, String testType) throws Exception { + public static void test(String loaderName, String expectedErrorMessage_part1, + String expectedErrorMessage_part2, String testType) throws Exception { String[] classNames = {testType}; ClassLoader l = new PreemptingClassLoader(loaderName, classNames, false); l.loadClass(testType); @@ -72,8 +80,9 @@ throw new RuntimeException("Expected LinkageError exception not thrown"); } catch (LinkageError e) { String errorMsg = e.getMessage(); - if (!errorMsg.equals(expectedErrorMessage)) { - System.out.println("Expected: " + expectedErrorMessage + "\n" + + if (!errorMsg.contains(expectedErrorMessage_part1) || + !errorMsg.contains(expectedErrorMessage_part2)) { + System.out.println("Expected: " + expectedErrorMessage_part1 + "" + expectedErrorMessage_part2 + "\n" + "but got: " + errorMsg); throw new RuntimeException("Wrong LinkageError exception thrown: " + errorMsg); } @@ -82,9 +91,9 @@ } public static void main(String args[]) throws Exception { - test(null, expectedErrorMessage1, "test.Foo"); - test("DuplicateLE_Test_Loader", expectedErrorMessage2, "test.Foo"); - test("DuplicateLE_Test_Loader_IF", expectedErrorMessage3, "test.J"); + test(null, expectedErrorMessage1_part1, expectedErrorMessage1_part2, "test.Foo"); + test("DuplicateLE_Test_Loader", expectedErrorMessage2_part1, expectedErrorMessage2_part2, "test.Foo"); + test("DuplicateLE_Test_Loader_IF", expectedErrorMessage3_part1, expectedErrorMessage3_part2, "test.J"); } } --- old/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Test.java 2018-06-13 19:39:40.370550128 -0400 +++ new/test/hotspot/jtreg/runtime/LoaderConstraints/itableLdrConstraint/Test.java 2018-06-13 19:39:38.899311544 -0400 @@ -35,22 +35,28 @@ public class Test { - static String expectedErrorMessage1 = + // Break expected error messages into 2 parts since the loader name includes its identity + // hash which is unique and can't be compared against. + static String expectedErrorMessage1_part1 = "loader constraint violation in interface itable initialization for class test.C: " + "when selecting method test.I.m()Ltest/Foo; " + - "the class loader \"\" (instance of PreemptingClassLoader, " + - "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + - "for super interface test.I, and the class loader \"app\" " + + "the class loader PreemptingClassLoader @"; + static String expectedErrorMessage1_part2 = + " (instance of PreemptingClassLoader, " + + "child of 'app' jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "for super interface test.I, and the class loader 'app' " + "(instance of jdk.internal.loader.ClassLoaders$AppClassLoader) " + "of the selected method's type, test.J have different Class objects " + "for the type test.Foo used in the signature"; - static String expectedErrorMessage2 = + static String expectedErrorMessage2_part1 = "loader constraint violation in interface itable initialization for class test.C: " + "when selecting method test.I.m()Ltest/Foo; " + - "the class loader \"ItableLdrCnstrnt_Test_Loader\" (instance of PreemptingClassLoader, " + - "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + - "for super interface test.I, and the class loader \"app\" " + + "the class loader 'ItableLdrCnstrnt_Test_Loader' @"; + static String expectedErrorMessage2_part2 = + " (instance of PreemptingClassLoader, " + + "child of 'app' jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "for super interface test.I, and the class loader 'app' " + "(instance of jdk.internal.loader.ClassLoaders$AppClassLoader) " + "of the selected method's type, test.J have different Class objects " + "for the type test.Foo used in the signature"; @@ -63,7 +69,9 @@ // type super interface J. The selected method is not an overpass method nor // otherwise excluded from loader constraint checking. So, a LinkageError // exception should be thrown because the loader constraint check will fail. - public static void test(String loaderName, String expectedErrorMessage) throws Exception { + public static void test(String loaderName, + String expectedErrorMessage_part1, + String expectedErrorMessage_part2) throws Exception { Class c = test.Foo.class; // Forces standard class loader to load Foo. String[] classNames = {"test.Task", "test.Foo", "test.C", "test.I"}; ClassLoader l = new PreemptingClassLoader(loaderName, classNames); @@ -73,8 +81,9 @@ throw new RuntimeException("Expected LinkageError exception not thrown"); } catch (LinkageError e) { String errorMsg = e.getMessage(); - if (!errorMsg.equals(expectedErrorMessage)) { - System.out.println("Expected: " + expectedErrorMessage + "\n" + + if (!errorMsg.contains(expectedErrorMessage_part1) || + !errorMsg.contains(expectedErrorMessage_part2)) { + System.out.println("Expected: " + expectedErrorMessage_part1 + "" + expectedErrorMessage_part2 + "\n" + "but got: " + errorMsg); throw new RuntimeException("Wrong LinkageError exception thrown: " + errorMsg); } @@ -83,7 +92,7 @@ } public static void main(String... args) throws Exception { - test(null, expectedErrorMessage1); - test("ItableLdrCnstrnt_Test_Loader", expectedErrorMessage2); + test(null, expectedErrorMessage1_part1, expectedErrorMessage1_part2); + test("ItableLdrCnstrnt_Test_Loader", expectedErrorMessage2_part1, expectedErrorMessage2_part2); } } --- old/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Test.java 2018-06-13 19:39:52.922869469 -0400 +++ new/test/hotspot/jtreg/runtime/LoaderConstraints/vtableLdrConstraint/Test.java 2018-06-13 19:39:51.524180566 -0400 @@ -35,23 +35,29 @@ public class Test { - static String expectedErrorMessage1 = + // Break expected error messages into 2 parts since the loader name includes its identity + // hash which is unique and can't be compared against. + static String expectedErrorMessage1_part1 = "loader constraint violation for class test.Task: " + "when selecting overriding method test.Task.m()Ltest/Foo; " + - "the class loader \"\" (instance of PreemptingClassLoader, " + - "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "the class loader PreemptingClassLoader @"; + static String expectedErrorMessage1_part2 = + " (instance of PreemptingClassLoader, " + + "child of 'app' jdk.internal.loader.ClassLoaders$AppClassLoader) " + "of the selected method's type test.Task, " + - "and the class loader \"app\" (instance of jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "and the class loader 'app' (instance of jdk.internal.loader.ClassLoaders$AppClassLoader) " + "for its super type test.J " + "have different Class objects for the type test.Foo used in the signature"; - static String expectedErrorMessage2 = + static String expectedErrorMessage2_part1 = "loader constraint violation for class test.Task: " + "when selecting overriding method test.Task.m()Ltest/Foo; " + - "the class loader \"VtableLdrCnstrnt_Test_Loader\" (instance of PreemptingClassLoader, " + - "child of \"app\" jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "the class loader 'VtableLdrCnstrnt_Test_Loader' @"; + static String expectedErrorMessage2_part2 = + " (instance of PreemptingClassLoader, " + + "child of 'app' jdk.internal.loader.ClassLoaders$AppClassLoader) " + "of the selected method's type test.Task, " + - "and the class loader \"app\" (instance of jdk.internal.loader.ClassLoaders$AppClassLoader) " + + "and the class loader 'app' (instance of jdk.internal.loader.ClassLoaders$AppClassLoader) " + "for its super type test.J " + "have different Class objects for the type test.Foo used in the signature"; @@ -62,7 +68,9 @@ // overrides "J.m()LFoo;". But, Task's class Foo and super type J's class Foo // are different. So, a LinkageError exception should be thrown because the // loader constraint check will fail. - public static void test(String loaderName, String expectedErrorMessage) throws Exception { + public static void test(String loaderName, + String expectedErrorMessage_part1, + String expectedErrorMessage_part2) throws Exception { Class c = test.Foo.class; // Forces standard class loader to load Foo. String[] classNames = {"test.Task", "test.Foo", "test.I"}; ClassLoader l = new PreemptingClassLoader(loaderName, classNames); @@ -72,8 +80,9 @@ throw new RuntimeException("Expected LinkageError exception not thrown"); } catch (LinkageError e) { String errorMsg = e.getMessage(); - if (!errorMsg.equals(expectedErrorMessage)) { - System.out.println("Expected: " + expectedErrorMessage + "\n" + + if (!errorMsg.contains(expectedErrorMessage_part1) || + !errorMsg.contains(expectedErrorMessage_part2)) { + System.out.println("Expected: " + expectedErrorMessage_part1 + "" + expectedErrorMessage_part2 + "\n" + "but got: " + errorMsg); throw new RuntimeException("Wrong LinkageError exception thrown: " + errorMsg); } @@ -82,8 +91,8 @@ } public static void main(String args[]) throws Exception { - test(null, expectedErrorMessage1); - test("VtableLdrCnstrnt_Test_Loader", expectedErrorMessage2); + test(null, expectedErrorMessage1_part1, expectedErrorMessage1_part2); + test("VtableLdrCnstrnt_Test_Loader", expectedErrorMessage2_part1, expectedErrorMessage2_part2); } } --- old/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java 2018-06-13 19:40:04.353462682 -0400 +++ new/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java 2018-06-13 19:40:02.949089344 -0400 @@ -74,7 +74,7 @@ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.metaspace", "show-loaders"}); output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); - output.shouldMatch("CLD.*"); + output.shouldMatch("CLD.*'bootstrap'"); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.metaspace", "by-chunktype"}); output = new OutputAnalyzer(pb.start()); --- old/test/hotspot/jtreg/runtime/SharedArchiveFile/DumpSymbolAndStringTable.java 2018-06-13 19:40:16.007006010 -0400 +++ new/test/hotspot/jtreg/runtime/SharedArchiveFile/DumpSymbolAndStringTable.java 2018-06-13 19:40:14.606673395 -0400 @@ -60,7 +60,7 @@ pb.command(new String[] {JDKToolFinder.getJDKTool("jcmd"), pid, "VM.systemdictionary"}); output = CDSTestUtils.executeAndLog(pb, "jcmd-systemdictionary"); try { - output.shouldContain("System Dictionary for jdk/internal/loader/ClassLoaders$AppClassLoader statistics:"); + output.shouldContain("System Dictionary for 'app' class loader statistics:"); output.shouldContain("Number of buckets"); output.shouldContain("Number of entries"); output.shouldContain("Maximum bucket size"); --- old/test/hotspot/jtreg/runtime/logging/LoaderConstraintsTest.java 2018-06-13 19:40:27.433975525 -0400 +++ new/test/hotspot/jtreg/runtime/logging/LoaderConstraintsTest.java 2018-06-13 19:40:26.034632715 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,12 +67,12 @@ pb = exec("-XX:+TraceLoaderConstraints"); out = new OutputAnalyzer(pb.start()); out.getOutput(); - out.shouldContain("[class,loader,constraints] adding new constraint for name: java/lang/Class, loader[0]: jdk/internal/loader/ClassLoaders$AppClassLoader, loader[1]: "); + out.shouldContain("[class,loader,constraints] adding new constraint for name: java/lang/Class, loader[0]: 'app', loader[1]: 'bootstrap'"); // -Xlog:class+loader+constraints=info pb = exec("-Xlog:class+loader+constraints=info"); out = new OutputAnalyzer(pb.start()); - out.shouldContain("[class,loader,constraints] adding new constraint for name: java/lang/Class, loader[0]: jdk/internal/loader/ClassLoaders$AppClassLoader, loader[1]: "); + out.shouldContain("[class,loader,constraints] adding new constraint for name: java/lang/Class, loader[0]: 'app', loader[1]: 'bootstrap'"); // -XX:-TraceLoaderConstraints pb = exec("-XX:-TraceLoaderConstraints"); --- old/test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderHierarchyTest.java 2018-06-13 19:40:40.403551180 -0400 +++ new/test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderHierarchyTest.java 2018-06-13 19:40:38.924565624 -0400 @@ -48,11 +48,11 @@ public class ClassLoaderHierarchyTest { -//+-- +//+-- "'bootstrap'" // | -// +-- "platform", jdk.internal.loader.ClassLoaders$PlatformClassLoader +// +-- "'platform'", jdk.internal.loader.ClassLoaders$PlatformClassLoader // | | -// | +-- "app", jdk.internal.loader.ClassLoaders$AppClassLoader +// | +-- "'app'", jdk.internal.loader.ClassLoaders$AppClassLoader // | // +-- jdk.internal.reflect.DelegatingClassLoader // | @@ -84,14 +84,14 @@ // First test: simple output, no classes displayed OutputAnalyzer output = executor.execute("VM.classloaders"); - output.shouldContain(""); + output.shouldContain("'bootstrap'"); output.shouldMatch(".*TestClassLoader"); output.shouldMatch("Kevin.*TestClassLoader"); output.shouldMatch("Bill.*TestClassLoader"); // Second test: print with classes. output = executor.execute("VM.classloaders show-classes"); - output.shouldContain(""); + output.shouldContain("'bootstrap'"); output.shouldContain("java.lang.Object"); output.shouldMatch(".*TestClassLoader"); output.shouldMatch("Kevin.*TestClassLoader"); --- old/test/jdk/jdk/jfr/event/runtime/TestClassLoadEvent.java 2018-06-13 19:40:54.123336068 -0400 +++ new/test/jdk/jdk/jfr/event/runtime/TestClassLoadEvent.java 2018-06-13 19:40:52.724006993 -0400 @@ -47,7 +47,7 @@ public final class TestClassLoadEvent { private final static String TEST_CLASS_NAME = "jdk.jfr.event.runtime.TestClasses"; - private final static String BOOT_CLASS_LOADER_NAME = "boot"; + private final static String BOOT_CLASS_LOADER_NAME = "'bootstrap'"; private final static String SEARCH_CLASS_NAME = "java.lang.Object"; private final static String SEARCH_PACKAGE_NAME = "java/lang"; private final static String SEARCH_MODULE_NAME = "java.base";