1 /*
   2  * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2018 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #include "precompiled.hpp"
  27 
  28 #include "classfile/classLoaderData.inline.hpp"
  29 #include "classfile/classLoaderDataGraph.hpp"
  30 #include "classfile/classLoaderHierarchyDCmd.hpp"
  31 #include "memory/allocation.hpp"
  32 #include "memory/resourceArea.hpp"
  33 #include "runtime/safepoint.hpp"
  34 #include "oops/reflectionAccessorImplKlassHelper.hpp"
  35 #include "utilities/globalDefinitions.hpp"
  36 #include "utilities/ostream.hpp"
  37 
  38 
  39 ClassLoaderHierarchyDCmd::ClassLoaderHierarchyDCmd(outputStream* output, bool heap)
  40   : DCmdWithParser(output, heap),
  41    _show_classes("show-classes", "Print loaded classes.", "BOOLEAN", false, "false"),
  42   _verbose("verbose", "Print detailed information.", "BOOLEAN", false, "false"),
  43   _fold("fold", "Show loaders of the same name and class as one.", "BOOLEAN", true, "true") {
  44   _dcmdparser.add_dcmd_option(&_show_classes);
  45   _dcmdparser.add_dcmd_option(&_verbose);
  46   _dcmdparser.add_dcmd_option(&_fold);
  47 }
  48 
  49 
  50 int ClassLoaderHierarchyDCmd::num_arguments() {
  51   ResourceMark rm;
  52   ClassLoaderHierarchyDCmd* dcmd = new ClassLoaderHierarchyDCmd(NULL, false);
  53   if (dcmd != NULL) {
  54     DCmdMark mark(dcmd);
  55     return dcmd->_dcmdparser.num_arguments();
  56   } else {
  57     return 0;
  58   }
  59 }
  60 
  61 // Helper class for drawing the branches to the left of a node.
  62 class BranchTracker : public StackObj {
  63   //       "<x>"
  64   //       " |---<y>"
  65   //       " |    |
  66   //       " |   <z>"
  67   //       " |    |---<z1>
  68   //       " |    |---<z2>
  69   //       ^^^^^^^ ^^^
  70   //        A       B
  71 
  72   // Some terms for the graphics:
  73   // - branch: vertical connection between a node's ancestor to a later sibling.
  74   // - branchwork: (A) the string to print as a prefix at the start of each line, contains all branches.
  75   // - twig (B): Length of the dashed line connecting a node to its branch.
  76   // - branch spacing: how many spaces between branches are printed.
  77 
  78 public:
  79 
  80   enum { max_depth = 64, twig_len = 2, branch_spacing = 5 };
  81 
  82 private:
  83 
  84   char _branches[max_depth];
  85   int _pos;
  86 
  87 public:
  88   BranchTracker()
  89     : _pos(0) {}
  90 
  91   void push(bool has_branch) {
  92     if (_pos < max_depth) {
  93       _branches[_pos] = has_branch ? '|' : ' ';
  94     }
  95     _pos ++; // beyond max depth, omit branch drawing but do count on.
  96   }
  97 
  98   void pop() {
  99     assert(_pos > 0, "must be");
 100     _pos --;
 101   }
 102 
 103   void print(outputStream* st) {
 104     for (int i = 0; i < _pos; i ++) {
 105       st->print("%c%.*s", _branches[i], branch_spacing, "          ");
 106     }
 107   }
 108 
 109   class Mark {
 110     BranchTracker& _tr;
 111   public:
 112     Mark(BranchTracker& tr, bool has_branch_here)
 113       : _tr(tr)  { _tr.push(has_branch_here); }
 114     ~Mark() { _tr.pop(); }
 115   };
 116 
 117 }; // end: BranchTracker
 118 
 119 struct LoadedClassInfo : public ResourceObj {
 120 public:
 121   LoadedClassInfo* _next;
 122   Klass* const _klass;
 123   const ClassLoaderData* const _cld;
 124 
 125   LoadedClassInfo(Klass* klass, const ClassLoaderData* cld)
 126     : _klass(klass), _cld(cld) {}
 127 
 128 };
 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 
 169     // Retrieve information.
 170     const Klass* const loader_klass = _cld->class_loader_klass();
 171     const Symbol* const loader_name = _cld->name();
 172 
 173     branchtracker.print(st);
 174 
 175     // e.g. "+--- jdk.internal.reflect.DelegatingClassLoader"
 176     st->print("+%.*s", BranchTracker::twig_len, "----------");
 177     if (_cld->is_the_null_class_loader_data()) {
 178       st->print(" <bootstrap>");
 179     } 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());
 183       }
 184       st->print(" %s", loader_klass != NULL ? loader_klass->external_name() : "??");
 185       if (_num_folded > 0) {
 186         st->print(" (+ %d more)", _num_folded);
 187       }
 188     }
 189     st->cr();
 190 
 191     // Output following this node (node details and child nodes) - up to the next sibling node
 192     // needs to be prefixed with "|" if there is a follow up sibling.
 193     const bool have_sibling = _next != NULL;
 194     BranchTracker::Mark trm(branchtracker, have_sibling);
 195 
 196     {
 197       // optional node details following this node needs to be prefixed with "|"
 198       // if there are follow up child nodes.
 199       const bool have_child = _child != NULL;
 200       BranchTracker::Mark trm(branchtracker, have_child);
 201 
 202       // Empty line
 203       branchtracker.print(st);
 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,
 274                        (_num_hidden_classes == 1) ? "" : "es");
 275 
 276           // Empty line
 277           branchtracker.print(st);
 278           st->cr();
 279         }
 280 
 281       } // end: print_classes
 282 
 283     } // Pop branchtracker mark
 284 
 285     // Print children, recursively
 286     LoaderTreeNode* c = _child;
 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) {
 361         result = c->find(loader_oop);
 362         c = c->_next;
 363       }
 364     }
 365     return result;
 366   }
 367 
 368   bool is_leaf() const { return _child == NULL; }
 369 
 370   // Attempt to fold similar nodes among this node's children. We only fold leaf nodes
 371   // (no child class loaders).
 372   // For non-leaf nodes (class loaders with child class loaders), do this recursivly.
 373   void fold_children() {
 374     LoaderTreeNode* node = _child;
 375     LoaderTreeNode* prev = NULL;
 376     while (node != NULL) {
 377       LoaderTreeNode* matching_node = NULL;
 378       if (node->is_leaf()) {
 379         // Look among the preceeding node siblings for a match.
 380         for (LoaderTreeNode* node2 = _child; node2 != node && matching_node == NULL;
 381             node2 = node2->_next) {
 382           if (node2->is_leaf() && node->can_fold_into(node2)) {
 383             matching_node = node2;
 384           }
 385         }
 386       } else {
 387         node->fold_children();
 388       }
 389       if (matching_node != NULL) {
 390         // Increase fold count for the matching node and remove folded node from the child list.
 391         matching_node->_num_folded ++;
 392         assert(prev != NULL, "Sanity"); // can never happen since we do not fold the first node.
 393         prev->_next = node->_next;
 394       } else {
 395         prev = node;
 396       }
 397       node = node->_next;
 398     }
 399   }
 400 
 401   void print_with_childs(outputStream* st, bool print_classes, bool print_add_info) const {
 402     BranchTracker bwt;
 403     print_with_childs(st, bwt, print_classes, print_add_info);
 404   }
 405 
 406 };
 407 
 408 class LoadedClassCollectClosure : public KlassClosure {
 409 public:
 410   LoadedClassInfo* _list;
 411   const ClassLoaderData* _cld;
 412   int _num_classes;
 413   LoadedClassCollectClosure(const ClassLoaderData* cld)
 414     : _list(NULL), _cld(cld), _num_classes(0) {}
 415   void do_klass(Klass* k) {
 416     LoadedClassInfo* lki = new LoadedClassInfo(k, _cld);
 417     lki->_next = _list;
 418     _list = lki;
 419     _num_classes ++;
 420   }
 421 };
 422 
 423 class LoaderInfoScanClosure : public CLDClosure {
 424 
 425   const bool _print_classes;
 426   const bool _verbose;
 427   LoaderTreeNode* _root;
 428 
 429   static void fill_in_classes(LoaderTreeNode* info, const ClassLoaderData* cld) {
 430     assert(info != NULL && cld != NULL, "must be");
 431     LoadedClassCollectClosure lccc(cld);
 432     const_cast<ClassLoaderData*>(cld)->classes_do(&lccc);
 433     if (lccc._num_classes > 0) {
 434       info->add_classes(lccc._list, lccc._num_classes, cld->has_class_mirror_holder());
 435     }
 436   }
 437 
 438   LoaderTreeNode* find_node_or_add_empty_node(oop loader_oop) {
 439 
 440     assert(_root != NULL, "root node must exist");
 441 
 442     if (loader_oop == NULL) {
 443       return _root;
 444     }
 445 
 446     // Check if a node for this oop already exists.
 447     LoaderTreeNode* info = _root->find(loader_oop);
 448 
 449     if (info == NULL) {
 450       // It does not. Create a node.
 451       info = new LoaderTreeNode(loader_oop);
 452 
 453       // Add it to tree.
 454       LoaderTreeNode* parent_info = NULL;
 455 
 456       // Recursively add parent nodes if needed.
 457       const oop parent_oop = java_lang_ClassLoader::parent(loader_oop);
 458       if (parent_oop == NULL) {
 459         parent_info = _root;
 460       } else {
 461         parent_info = find_node_or_add_empty_node(parent_oop);
 462       }
 463       assert(parent_info != NULL, "must be");
 464 
 465       parent_info->add_child(info);
 466     }
 467     return info;
 468   }
 469 
 470 
 471 public:
 472   LoaderInfoScanClosure(bool print_classes, bool verbose)
 473     : _print_classes(print_classes), _verbose(verbose), _root(NULL) {
 474     _root = new LoaderTreeNode(NULL);
 475   }
 476 
 477   void print_results(outputStream* st) const {
 478     _root->print_with_childs(st, _print_classes, _verbose);
 479   }
 480 
 481   void do_cld (ClassLoaderData* cld) {
 482 
 483     // We do not display unloading loaders, for now.
 484     if (!cld->is_alive()) {
 485       return;
 486     }
 487 
 488     const oop loader_oop = cld->class_loader();
 489 
 490     LoaderTreeNode* info = find_node_or_add_empty_node(loader_oop);
 491     assert(info != NULL, "must be");
 492 
 493     // Update CLD in node, but only if this is the primary CLD for this loader.
 494     if (cld->has_class_mirror_holder() == false) {
 495       assert(info->cld() == NULL, "there should be only one primary CLD per loader");
 496       info->set_cld(cld);
 497     }
 498 
 499     // Add classes.
 500     fill_in_classes(info, cld);
 501   }
 502 
 503   void fold() {
 504     _root->fold_children();
 505   }
 506 
 507 };
 508 
 509 
 510 class ClassLoaderHierarchyVMOperation : public VM_Operation {
 511   outputStream* const _out;
 512   const bool _show_classes;
 513   const bool _verbose;
 514   const bool _fold;
 515 public:
 516   ClassLoaderHierarchyVMOperation(outputStream* out, bool show_classes, bool verbose, bool fold) :
 517     _out(out), _show_classes(show_classes), _verbose(verbose), _fold(fold)
 518   {}
 519 
 520   VMOp_Type type() const {
 521     return VMOp_ClassLoaderHierarchyOperation;
 522   }
 523 
 524   void doit() {
 525     assert(SafepointSynchronize::is_at_safepoint(), "must be a safepoint");
 526     ResourceMark rm;
 527     LoaderInfoScanClosure cl (_show_classes, _verbose);
 528     ClassLoaderDataGraph::loaded_cld_do(&cl);
 529     // In non-verbose and non-show-classes mode, attempt to fold the tree.
 530     if (_fold) {
 531       if (!_verbose && !_show_classes) {
 532         cl.fold();
 533       }
 534     }
 535     cl.print_results(_out);
 536   }
 537 };
 538 
 539 // This command needs to be executed at a safepoint.
 540 void ClassLoaderHierarchyDCmd::execute(DCmdSource source, TRAPS) {
 541   ClassLoaderHierarchyVMOperation op(output(), _show_classes.value(), _verbose.value(), _fold.value());
 542   VMThread::execute(&op);
 543 }