@@ -123,7 +123,7 @@ struct LoadedClassInfo : public ResourceObj {
123123 const ClassLoaderData* const _cld;
124124
125125 LoadedClassInfo (Klass* klass, const ClassLoaderData* cld)
126- : _klass(klass), _cld(cld) {}
126+ : _next( NULL ), _klass(klass), _cld(cld) {}
127127
128128};
129129
@@ -138,7 +138,7 @@ class LoaderTreeNode : public ResourceObj {
138138 // this parent loader, we fill in all the other details.
139139
140140 const oop _loader_oop;
141- const ClassLoaderData* _cld;
141+ const ClassLoaderData* _cld; // May be NULL if loader never loaded anything
142142
143143 LoaderTreeNode* _child;
144144 LoaderTreeNode* _next;
@@ -155,33 +155,59 @@ class LoaderTreeNode : public ResourceObj {
155155 // one.
156156 int _num_folded;
157157
158- void print_with_childs (outputStream* st, BranchTracker& branchtracker,
159- bool print_classes, bool verbose) const {
158+ // Returns Klass of loader; NULL for bootstrap loader
159+ const Klass* loader_klass () const {
160+ return (_loader_oop != NULL ) ? _loader_oop->klass () : NULL ;
161+ }
160162
161- ResourceMark rm;
163+ // Returns ResourceArea-allocated class name of loader class; "" if there is no klass (bootstrap loader)
164+ const char * loader_class_name () const {
165+ const Klass* klass = loader_klass ();
166+ return klass != NULL ? klass->external_name () : " " ;
167+ }
162168
163- if (_cld == NULL ) {
164- // Not sure how this could happen: we added a preliminary node for a parent but then never encountered
165- // its CLD?
166- return ;
169+ // Returns oop of loader name; NULL for bootstrap; NULL if no name was set
170+ oop loader_name_oop () const {
171+ return (_loader_oop != NULL ) ? java_lang_ClassLoader::name (_loader_oop) : NULL ;
172+ }
173+
174+ // Returns ResourceArea-allocated name of loader, "" if none is set
175+ const char * loader_name () const {
176+ oop name_oop = loader_name_oop ();
177+ return name_oop != NULL ? java_lang_String::as_utf8_string (name_oop) : " " ;
178+ }
179+
180+ bool is_bootstrap () const {
181+ if (_loader_oop == NULL ) {
182+ assert (_cld != NULL && _cld->is_boot_class_loader_data (), " bootstrap loader must have CLD" );
183+ return true ;
167184 }
185+ return false ;
186+ }
187+
188+ void print_with_child_nodes (outputStream* st, BranchTracker& branchtracker,
189+ bool print_classes, bool verbose) const {
190+
191+ assert (SafepointSynchronize::is_at_safepoint (), " invariant" );
192+
193+ ResourceMark rm;
168194
169195 // Retrieve information.
170- const Klass* const loader_klass = _cld->class_loader_klass ();
171- const Symbol* const loader_name = _cld->name ();
196+ const Klass* const the_loader_klass = loader_klass ();
197+ const char * const the_loader_class_name = loader_class_name ();
198+ const char * const the_loader_name = loader_name ();
172199
173200 branchtracker.print (st);
174201
175202 // e.g. "+--- jdk.internal.reflect.DelegatingClassLoader"
176203 st->print (" +%.*s" , BranchTracker::twig_len, " ----------" );
177- if (_cld-> is_the_null_class_loader_data ()) {
204+ if (is_bootstrap ()) {
178205 st->print (" <bootstrap>" );
179206 } else {
180- assert (!_cld->has_class_mirror_holder (), " _cld must be the primary cld" );
181- if (loader_name != NULL ) {
182- st->print (" \" %s\" ," , loader_name->as_C_string ());
207+ if (the_loader_name[0 ] != ' \0 ' ) {
208+ st->print (" \" %s\" ," , the_loader_name);
183209 }
184- st->print (" %s" , loader_klass != NULL ? loader_klass-> external_name () : " ?? " );
210+ st->print (" %s" , the_loader_class_name );
185211 if (_num_folded > 0 ) {
186212 st->print (" (+ %d more)" , _num_folded);
187213 }
@@ -211,7 +237,7 @@ class LoaderTreeNode : public ResourceObj {
211237 branchtracker.print (st);
212238 st->print_cr (" %*s " PTR_FORMAT, indentation, " Loader Data:" , p2i (_cld));
213239 branchtracker.print (st);
214- st->print_cr (" %*s " PTR_FORMAT, indentation, " Loader Klass:" , p2i (loader_klass ));
240+ st->print_cr (" %*s " PTR_FORMAT, indentation, " Loader Klass:" , p2i (the_loader_klass ));
215241
216242 // Empty line
217243 branchtracker.print (st);
@@ -220,6 +246,7 @@ class LoaderTreeNode : public ResourceObj {
220246
221247 if (print_classes) {
222248 if (_classes != NULL ) {
249+ assert (_cld != NULL , " we have classes, we should have a CLD" );
223250 for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next ) {
224251 // non-strong hidden classes should not live in
225252 // the primary CLD of their loaders.
@@ -252,6 +279,7 @@ class LoaderTreeNode : public ResourceObj {
252279 }
253280
254281 if (_hidden_classes != NULL ) {
282+ assert (_cld != NULL , " we have classes, we should have a CLD" );
255283 for (LoadedClassInfo* lci = _hidden_classes; lci; lci = lci->_next ) {
256284 branchtracker.print (st);
257285 if (lci == _hidden_classes) { // first iteration
@@ -285,7 +313,7 @@ class LoaderTreeNode : public ResourceObj {
285313 // Print children, recursively
286314 LoaderTreeNode* c = _child;
287315 while (c != NULL ) {
288- c->print_with_childs (st, branchtracker, print_classes, verbose);
316+ c->print_with_child_nodes (st, branchtracker, print_classes, verbose);
289317 c = c->_next ;
290318 }
291319
@@ -294,10 +322,21 @@ class LoaderTreeNode : public ResourceObj {
294322 // Helper: Attempt to fold this node into the target node. If success, returns true.
295323 // Folding can be done if both nodes are leaf nodes and they refer to the same loader class
296324 // and they have the same name or no name (note: leaf check is done by caller).
297- bool can_fold_into (LoaderTreeNode* target_node) const {
325+ bool can_fold_into (const LoaderTreeNode* target_node) const {
298326 assert (is_leaf () && target_node->is_leaf (), " must be leaf" );
299- return _cld->class_loader_klass () == target_node->_cld ->class_loader_klass () &&
300- _cld->name () == target_node->_cld ->name ();
327+
328+ // Must have the same non-null klass
329+ const Klass* k = loader_klass ();
330+ if (k == NULL || k != target_node->loader_klass ()) {
331+ return false ;
332+ }
333+
334+ // Must have the same loader name, or none
335+ if (::strcmp (loader_name (), target_node->loader_name ()) != 0 ) {
336+ return false ;
337+ }
338+
339+ return true ;
301340 }
302341
303342public:
@@ -309,6 +348,7 @@ class LoaderTreeNode : public ResourceObj {
309348 {}
310349
311350 void set_cld (const ClassLoaderData* cld) {
351+ assert (_cld == NULL , " there should be only one primary CLD per loader" );
312352 _cld = cld;
313353 }
314354
@@ -343,14 +383,6 @@ class LoaderTreeNode : public ResourceObj {
343383 }
344384 }
345385
346- const ClassLoaderData* cld () const {
347- return _cld;
348- }
349-
350- const oop loader_oop () const {
351- return _loader_oop;
352- }
353-
354386 LoaderTreeNode* find (const oop loader_oop) {
355387 LoaderTreeNode* result = NULL ;
356388 if (_loader_oop == loader_oop) {
@@ -373,6 +405,7 @@ class LoaderTreeNode : public ResourceObj {
373405 void fold_children () {
374406 LoaderTreeNode* node = _child;
375407 LoaderTreeNode* prev = NULL ;
408+ ResourceMark rm;
376409 while (node != NULL ) {
377410 LoaderTreeNode* matching_node = NULL ;
378411 if (node->is_leaf ()) {
@@ -398,9 +431,9 @@ class LoaderTreeNode : public ResourceObj {
398431 }
399432 }
400433
401- void print_with_childs (outputStream* st, bool print_classes, bool print_add_info) const {
434+ void print_with_child_nodes (outputStream* st, bool print_classes, bool print_add_info) const {
402435 BranchTracker bwt;
403- print_with_childs (st, bwt, print_classes, print_add_info);
436+ print_with_child_nodes (st, bwt, print_classes, print_add_info);
404437 }
405438
406439};
@@ -475,7 +508,7 @@ class LoaderInfoScanClosure : public CLDClosure {
475508 }
476509
477510 void print_results (outputStream* st) const {
478- _root->print_with_childs (st, _print_classes, _verbose);
511+ _root->print_with_child_nodes (st, _print_classes, _verbose);
479512 }
480513
481514 void do_cld (ClassLoaderData* cld) {
@@ -492,7 +525,6 @@ class LoaderInfoScanClosure : public CLDClosure {
492525
493526 // Update CLD in node, but only if this is the primary CLD for this loader.
494527 if (cld->has_class_mirror_holder () == false ) {
495- assert (info->cld () == NULL , " there should be only one primary CLD per loader" );
496528 info->set_cld (cld);
497529 }
498530
0 commit comments