--- old/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp 2020-03-26 15:57:25.000000000 -0700 +++ new/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp 2020-03-26 15:57:24.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -129,7 +129,7 @@ class LoaderTreeNode : public ResourceObj { - // We walk the CLDG and, for each CLD which is non-unsafe_anonymous, add + // We walk the CLDG and, for each CLD which is findable, add // a tree node. // To add a node we need its parent node; if the parent node does not yet // exist - because we have not yet encountered the CLD for the parent loader - @@ -149,6 +149,9 @@ LoadedClassInfo* _anon_classes; int _num_anon_classes; + LoadedClassInfo* _hidden_weak_classes; + int _num_hidden_weak_classes; + // In default view, similar tree nodes (same loader class, same name or no name) // are folded into each other to make the output more readable. // _num_folded contains the number of nodes which have been folded into this @@ -177,6 +180,7 @@ if (_cld->is_the_null_class_loader_data()) { st->print(" "); } else { + assert(!_cld->has_class_mirror_holder(), "_cld must be the primary cld"); if (loader_name != NULL) { st->print(" \"%s\",", loader_name->as_C_string()); } @@ -220,7 +224,7 @@ if (print_classes) { if (_classes != NULL) { for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next) { - // Non-unsafe anonymous classes should live in the primary CLD of its loader + // Weak-hidden and unsafe anonymous classes should not live in the primary CLD of their loaders. assert(lci->_cld == _cld, "must be"); branchtracker.print(st); @@ -258,7 +262,35 @@ st->print("%*s ", indentation, ""); } st->print("%s", lci->_klass->external_name()); - // For unsafe anonymous classes, also print CLD if verbose. Should be a different one than the primary CLD. + // For unsafe anonymous classes, also print CLD if verbose. Should + // be a different one than the primary CLD. + assert(lci->_cld != _cld, "must be"); + if (verbose) { + st->print(" (Loader Data: " PTR_FORMAT ")", p2i(lci->_cld)); + } + st->cr(); + } + branchtracker.print(st); + st->print("%*s ", indentation, ""); + st->print_cr("(%u unsafe anonymous class%s)", _num_anon_classes, + (_num_anon_classes == 1) ? "" : "es"); + + // Empty line + branchtracker.print(st); + st->cr(); + } + + if (_hidden_weak_classes != NULL) { + for (LoadedClassInfo* lci = _hidden_weak_classes; lci; lci = lci->_next) { + branchtracker.print(st); + if (lci == _hidden_weak_classes) { // first iteration + st->print("%*s ", indentation, "Weak Hidden Classes:"); + } else { + st->print("%*s ", indentation, ""); + } + st->print("%s", lci->_klass->external_name()); + // For weak hidden classes, also print CLD if verbose. Should be a + // different one than the primary CLD. assert(lci->_cld != _cld, "must be"); if (verbose) { st->print(" (Loader Data: " PTR_FORMAT ")", p2i(lci->_cld)); @@ -267,7 +299,8 @@ } branchtracker.print(st); st->print("%*s ", indentation, ""); - st->print_cr("(%u unsafe anonymous class%s)", _num_anon_classes, (_num_anon_classes == 1) ? "" : "es"); + st->print_cr("(%u weak hidden class%s)", _num_hidden_weak_classes, + (_num_hidden_weak_classes == 1) ? "" : "es"); // Empty line branchtracker.print(st); @@ -301,6 +334,7 @@ LoaderTreeNode(const oop loader_oop) : _loader_oop(loader_oop), _cld(NULL), _child(NULL), _next(NULL), _classes(NULL), _num_classes(0), _anon_classes(NULL), _num_anon_classes(0), + _hidden_weak_classes(NULL), _num_hidden_weak_classes(0), _num_folded(0) {} @@ -319,15 +353,25 @@ _next = info; } - void add_classes(LoadedClassInfo* first_class, int num_classes, bool is_unsafe_anonymous) { - LoadedClassInfo** p_list_to_add_to = is_unsafe_anonymous ? &_anon_classes : &_classes; + void add_classes(LoadedClassInfo* first_class, int num_classes, bool has_class_mirror_holder) { + LoadedClassInfo** p_list_to_add_to; + bool is_hidden = first_class->_klass->is_hidden(); + if (has_class_mirror_holder) { + p_list_to_add_to = is_hidden ? &_hidden_weak_classes : &_anon_classes; + } else { + p_list_to_add_to = &_classes; + } // Search tail. while ((*p_list_to_add_to) != NULL) { p_list_to_add_to = &(*p_list_to_add_to)->_next; } *p_list_to_add_to = first_class; - if (is_unsafe_anonymous) { - _num_anon_classes += num_classes; + if (has_class_mirror_holder) { + if (is_hidden) { + _num_hidden_weak_classes += num_classes; + } else { + _num_anon_classes += num_classes; + } } else { _num_classes += num_classes; } @@ -421,7 +465,7 @@ LoadedClassCollectClosure lccc(cld); const_cast(cld)->classes_do(&lccc); if (lccc._num_classes > 0) { - info->add_classes(lccc._list, lccc._num_classes, cld->is_unsafe_anonymous()); + info->add_classes(lccc._list, lccc._num_classes, cld->has_class_mirror_holder()); } } @@ -481,7 +525,7 @@ assert(info != NULL, "must be"); // Update CLD in node, but only if this is the primary CLD for this loader. - if (cld->is_unsafe_anonymous() == false) { + if (cld->has_class_mirror_holder() == false) { assert(info->cld() == NULL, "there should be only one primary CLD per loader"); info->set_cld(cld); }