129 130 class LoaderTreeNode : public ResourceObj { 131 132 // We walk the CLDG and, for each CLD which is findable, add 133 // a tree node. 134 // To add a node we need its parent node; if the parent node does not yet 135 // exist - because we have not yet encountered the CLD for the parent loader - 136 // we add a preliminary empty LoaderTreeNode for it. This preliminary node 137 // just contains the loader oop and nothing else. Once we encounter the CLD of 138 // this parent loader, we fill in all the other details. 139 140 const oop _loader_oop; 141 const ClassLoaderData* _cld; 142 143 LoaderTreeNode* _child; 144 LoaderTreeNode* _next; 145 146 LoadedClassInfo* _classes; 147 int _num_classes; 148 149 LoadedClassInfo* _anon_classes; 150 int _num_anon_classes; 151 152 LoadedClassInfo* _hidden_classes; 153 int _num_hidden_classes; 154 155 // In default view, similar tree nodes (same loader class, same name or no name) 156 // are folded into each other to make the output more readable. 157 // _num_folded contains the number of nodes which have been folded into this 158 // one. 159 int _num_folded; 160 161 void print_with_childs(outputStream* st, BranchTracker& branchtracker, 162 bool print_classes, bool verbose) const { 163 164 ResourceMark rm; 165 166 if (_cld == NULL) { 167 // Not sure how this could happen: we added a preliminary node for a parent but then never encountered 168 // its CLD? 169 return; 170 } 171 207 st->cr(); 208 209 const int indentation = 18; 210 211 if (verbose) { 212 branchtracker.print(st); 213 st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Oop:", p2i(_loader_oop)); 214 branchtracker.print(st); 215 st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Data:", p2i(_cld)); 216 branchtracker.print(st); 217 st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Klass:", p2i(loader_klass)); 218 219 // Empty line 220 branchtracker.print(st); 221 st->cr(); 222 } 223 224 if (print_classes) { 225 if (_classes != NULL) { 226 for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next) { 227 // non-strong hidden and unsafe anonymous classes should not live in the primary CLD of their loaders. 228 assert(lci->_cld == _cld, "must be"); 229 230 branchtracker.print(st); 231 if (lci == _classes) { // first iteration 232 st->print("%*s ", indentation, "Classes:"); 233 } else { 234 st->print("%*s ", indentation, ""); 235 } 236 st->print("%s", lci->_klass->external_name()); 237 238 // Special treatment for generated core reflection accessor classes: print invocation target. 239 if (ReflectionAccessorImplKlassHelper::is_generated_accessor(lci->_klass)) { 240 st->print(" (invokes: "); 241 ReflectionAccessorImplKlassHelper::print_invocation_target(st, lci->_klass); 242 st->print(")"); 243 } 244 245 st->cr(); 246 } 247 branchtracker.print(st); 248 st->print("%*s ", indentation, ""); 249 st->print_cr("(%u class%s)", _num_classes, (_num_classes == 1) ? "" : "es"); 250 251 // Empty line 252 branchtracker.print(st); 253 st->cr(); 254 } 255 256 if (_anon_classes != NULL) { 257 for (LoadedClassInfo* lci = _anon_classes; lci; lci = lci->_next) { 258 branchtracker.print(st); 259 if (lci == _anon_classes) { // first iteration 260 st->print("%*s ", indentation, "Unsafe Anonymous Classes:"); 261 } else { 262 st->print("%*s ", indentation, ""); 263 } 264 st->print("%s", lci->_klass->external_name()); 265 // For unsafe anonymous classes, also print CLD if verbose. Should 266 // be a different one than the primary CLD. 267 assert(lci->_cld != _cld, "must be"); 268 if (verbose) { 269 st->print(" (Loader Data: " PTR_FORMAT ")", p2i(lci->_cld)); 270 } 271 st->cr(); 272 } 273 branchtracker.print(st); 274 st->print("%*s ", indentation, ""); 275 st->print_cr("(%u unsafe anonymous class%s)", _num_anon_classes, 276 (_num_anon_classes == 1) ? "" : "es"); 277 278 // Empty line 279 branchtracker.print(st); 280 st->cr(); 281 } 282 283 if (_hidden_classes != NULL) { 284 for (LoadedClassInfo* lci = _hidden_classes; lci; lci = lci->_next) { 285 branchtracker.print(st); 286 if (lci == _hidden_classes) { // first iteration 287 st->print("%*s ", indentation, "Hidden Classes:"); 288 } else { 289 st->print("%*s ", indentation, ""); 290 } 291 st->print("%s", lci->_klass->external_name()); 292 // For non-strong hidden classes, also print CLD if verbose. Should be a 293 // different one than the primary CLD. 294 assert(lci->_cld != _cld, "must be"); 295 if (verbose) { 296 st->print(" (Loader Data: " PTR_FORMAT ")", p2i(lci->_cld)); 297 } 298 st->cr(); 299 } 300 branchtracker.print(st); 301 st->print("%*s ", indentation, ""); 302 st->print_cr("(%u hidden class%s)", _num_hidden_classes, 316 while (c != NULL) { 317 c->print_with_childs(st, branchtracker, print_classes, verbose); 318 c = c->_next; 319 } 320 321 } 322 323 // Helper: Attempt to fold this node into the target node. If success, returns true. 324 // Folding can be done if both nodes are leaf nodes and they refer to the same loader class 325 // and they have the same name or no name (note: leaf check is done by caller). 326 bool can_fold_into(LoaderTreeNode* target_node) const { 327 assert(is_leaf() && target_node->is_leaf(), "must be leaf"); 328 return _cld->class_loader_klass() == target_node->_cld->class_loader_klass() && 329 _cld->name() == target_node->_cld->name(); 330 } 331 332 public: 333 334 LoaderTreeNode(const oop loader_oop) 335 : _loader_oop(loader_oop), _cld(NULL), _child(NULL), _next(NULL), 336 _classes(NULL), _num_classes(0), _anon_classes(NULL), _num_anon_classes(0), 337 _hidden_classes(NULL), _num_hidden_classes(0), 338 _num_folded(0) 339 {} 340 341 void set_cld(const ClassLoaderData* cld) { 342 _cld = cld; 343 } 344 345 void add_child(LoaderTreeNode* info) { 346 info->_next = _child; 347 _child = info; 348 } 349 350 void add_sibling(LoaderTreeNode* info) { 351 assert(info->_next == NULL, "must be"); 352 info->_next = _next; 353 _next = info; 354 } 355 356 void add_classes(LoadedClassInfo* first_class, int num_classes, bool has_class_mirror_holder) { 357 LoadedClassInfo** p_list_to_add_to; 358 bool is_hidden = first_class->_klass->is_hidden(); 359 if (has_class_mirror_holder) { 360 p_list_to_add_to = is_hidden ? &_hidden_classes : &_anon_classes; 361 } else { 362 p_list_to_add_to = &_classes; 363 } 364 // Search tail. 365 while ((*p_list_to_add_to) != NULL) { 366 p_list_to_add_to = &(*p_list_to_add_to)->_next; 367 } 368 *p_list_to_add_to = first_class; 369 if (has_class_mirror_holder) { 370 if (is_hidden) { 371 _num_hidden_classes += num_classes; 372 } else { 373 _num_anon_classes += num_classes; 374 } 375 } else { 376 _num_classes += num_classes; 377 } 378 } 379 380 const ClassLoaderData* cld() const { 381 return _cld; 382 } 383 384 const oop loader_oop() const { 385 return _loader_oop; 386 } 387 388 LoaderTreeNode* find(const oop loader_oop) { 389 LoaderTreeNode* result = NULL; 390 if (_loader_oop == loader_oop) { 391 result = this; 392 } else { 393 LoaderTreeNode* c = _child; 394 while (c != NULL && result == NULL) { | 129 130 class LoaderTreeNode : public ResourceObj { 131 132 // We walk the CLDG and, for each CLD which is findable, add 133 // a tree node. 134 // To add a node we need its parent node; if the parent node does not yet 135 // exist - because we have not yet encountered the CLD for the parent loader - 136 // we add a preliminary empty LoaderTreeNode for it. This preliminary node 137 // just contains the loader oop and nothing else. Once we encounter the CLD of 138 // this parent loader, we fill in all the other details. 139 140 const oop _loader_oop; 141 const ClassLoaderData* _cld; 142 143 LoaderTreeNode* _child; 144 LoaderTreeNode* _next; 145 146 LoadedClassInfo* _classes; 147 int _num_classes; 148 149 LoadedClassInfo* _hidden_classes; 150 int _num_hidden_classes; 151 152 // In default view, similar tree nodes (same loader class, same name or no name) 153 // are folded into each other to make the output more readable. 154 // _num_folded contains the number of nodes which have been folded into this 155 // one. 156 int _num_folded; 157 158 void print_with_childs(outputStream* st, BranchTracker& branchtracker, 159 bool print_classes, bool verbose) const { 160 161 ResourceMark rm; 162 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; 167 } 168 204 st->cr(); 205 206 const int indentation = 18; 207 208 if (verbose) { 209 branchtracker.print(st); 210 st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Oop:", p2i(_loader_oop)); 211 branchtracker.print(st); 212 st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Data:", p2i(_cld)); 213 branchtracker.print(st); 214 st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Klass:", p2i(loader_klass)); 215 216 // Empty line 217 branchtracker.print(st); 218 st->cr(); 219 } 220 221 if (print_classes) { 222 if (_classes != NULL) { 223 for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next) { 224 // non-strong hidden and unsafe anonymous classes should not live in 225 // the primary CLD of their loaders. 226 assert(lci->_cld == _cld, "must be"); 227 228 branchtracker.print(st); 229 if (lci == _classes) { // first iteration 230 st->print("%*s ", indentation, "Classes:"); 231 } else { 232 st->print("%*s ", indentation, ""); 233 } 234 st->print("%s", lci->_klass->external_name()); 235 236 // Special treatment for generated core reflection accessor classes: print invocation target. 237 if (ReflectionAccessorImplKlassHelper::is_generated_accessor(lci->_klass)) { 238 st->print(" (invokes: "); 239 ReflectionAccessorImplKlassHelper::print_invocation_target(st, lci->_klass); 240 st->print(")"); 241 } 242 243 st->cr(); 244 } 245 branchtracker.print(st); 246 st->print("%*s ", indentation, ""); 247 st->print_cr("(%u class%s)", _num_classes, (_num_classes == 1) ? "" : "es"); 248 249 // Empty line 250 branchtracker.print(st); 251 st->cr(); 252 } 253 254 if (_hidden_classes != NULL) { 255 for (LoadedClassInfo* lci = _hidden_classes; lci; lci = lci->_next) { 256 branchtracker.print(st); 257 if (lci == _hidden_classes) { // first iteration 258 st->print("%*s ", indentation, "Hidden Classes:"); 259 } else { 260 st->print("%*s ", indentation, ""); 261 } 262 st->print("%s", lci->_klass->external_name()); 263 // For non-strong hidden classes, also print CLD if verbose. Should be a 264 // different one than the primary CLD. 265 assert(lci->_cld != _cld, "must be"); 266 if (verbose) { 267 st->print(" (Loader Data: " PTR_FORMAT ")", p2i(lci->_cld)); 268 } 269 st->cr(); 270 } 271 branchtracker.print(st); 272 st->print("%*s ", indentation, ""); 273 st->print_cr("(%u hidden class%s)", _num_hidden_classes, 287 while (c != NULL) { 288 c->print_with_childs(st, branchtracker, print_classes, verbose); 289 c = c->_next; 290 } 291 292 } 293 294 // Helper: Attempt to fold this node into the target node. If success, returns true. 295 // Folding can be done if both nodes are leaf nodes and they refer to the same loader class 296 // 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 { 298 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(); 301 } 302 303 public: 304 305 LoaderTreeNode(const oop loader_oop) 306 : _loader_oop(loader_oop), _cld(NULL), _child(NULL), _next(NULL), 307 _classes(NULL), _num_classes(0), _hidden_classes(NULL), 308 _num_hidden_classes(0), _num_folded(0) 309 {} 310 311 void set_cld(const ClassLoaderData* cld) { 312 _cld = cld; 313 } 314 315 void add_child(LoaderTreeNode* info) { 316 info->_next = _child; 317 _child = info; 318 } 319 320 void add_sibling(LoaderTreeNode* info) { 321 assert(info->_next == NULL, "must be"); 322 info->_next = _next; 323 _next = info; 324 } 325 326 void add_classes(LoadedClassInfo* first_class, int num_classes, bool has_class_mirror_holder) { 327 LoadedClassInfo** p_list_to_add_to; 328 bool is_hidden = first_class->_klass->is_hidden(); 329 if (has_class_mirror_holder) { 330 p_list_to_add_to = &_hidden_classes; 331 } else { 332 p_list_to_add_to = &_classes; 333 } 334 // Search tail. 335 while ((*p_list_to_add_to) != NULL) { 336 p_list_to_add_to = &(*p_list_to_add_to)->_next; 337 } 338 *p_list_to_add_to = first_class; 339 if (has_class_mirror_holder) { 340 _num_hidden_classes += num_classes; 341 } else { 342 _num_classes += num_classes; 343 } 344 } 345 346 const ClassLoaderData* cld() const { 347 return _cld; 348 } 349 350 const oop loader_oop() const { 351 return _loader_oop; 352 } 353 354 LoaderTreeNode* find(const oop loader_oop) { 355 LoaderTreeNode* result = NULL; 356 if (_loader_oop == loader_oop) { 357 result = this; 358 } else { 359 LoaderTreeNode* c = _child; 360 while (c != NULL && result == NULL) { |