1 /*
  2  * Copyright (c) 2018, 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/classLoaderHierarchyDCmd.hpp"
 30 #include "memory/allocation.hpp"
 31 #include "memory/resourceArea.hpp"
 32 #include "runtime/safepoint.hpp"
 33 #include "oops/reflectionAccessorImplKlassHelper.hpp"
 34 #include "utilities/globalDefinitions.hpp"
 35 #include "utilities/ostream.hpp"
 36 
 37 
 38 ClassLoaderHierarchyDCmd::ClassLoaderHierarchyDCmd(outputStream* output, bool heap)
 39   : DCmdWithParser(output, heap),
 40    _show_classes("show-classes", "Print loaded classes.", "BOOLEAN", false, "false"),
 41   _verbose("verbose", "Print detailed information.", "BOOLEAN", false, "false"),
 42   _fold("fold", "Show loaders of the same name and class as one.", "BOOLEAN", true, "true") {
 43   _dcmdparser.add_dcmd_option(&_show_classes);
 44   _dcmdparser.add_dcmd_option(&_verbose);
 45   _dcmdparser.add_dcmd_option(&_fold);
 46 }
 47 
 48 
 49 int ClassLoaderHierarchyDCmd::num_arguments() {
 50   ResourceMark rm;
 51   ClassLoaderHierarchyDCmd* dcmd = new ClassLoaderHierarchyDCmd(NULL, false);
 52   if (dcmd != NULL) {
 53     DCmdMark mark(dcmd);
 54     return dcmd->_dcmdparser.num_arguments();
 55   } else {
 56     return 0;
 57   }
 58 }
 59 
 60 // Helper class for drawing the branches to the left of a node.
 61 class BranchTracker : public StackObj {
 62   //       "<x>"
 63   //       " |---<y>"
 64   //       " |    |
 65   //       " |   <z>"
 66   //       " |    |---<z1>
 67   //       " |    |---<z2>
 68   //       ^^^^^^^ ^^^
 69   //        A       B
 70 
 71   // Some terms for the graphics:
 72   // - branch: vertical connection between a node's ancestor to a later sibling.
 73   // - branchwork: (A) the string to print as a prefix at the start of each line, contains all branches.
 74   // - twig (B): Length of the dashed line connecting a node to its branch.
 75   // - branch spacing: how many spaces between branches are printed.
 76 
 77 public:
 78 
 79   enum { max_depth = 64, twig_len = 2, branch_spacing = 5 };
 80 
 81 private:
 82 
 83   char _branches[max_depth];
 84   int _pos;
 85 
 86 public:
 87   BranchTracker()
 88     : _pos(0) {}
 89 
 90   void push(bool has_branch) {
 91     if (_pos < max_depth) {
 92       _branches[_pos] = has_branch ? '|' : ' ';
 93     }
 94     _pos ++; // beyond max depth, omit branch drawing but do count on.
 95   }
 96 
 97   void pop() {
 98     assert(_pos > 0, "must be");
 99     _pos --;
100   }
101 
102   void print(outputStream* st) {
103     for (int i = 0; i < _pos; i ++) {
104       st->print("%c%.*s", _branches[i], branch_spacing, "          ");
105     }
106   }
107 
108   class Mark {
109     BranchTracker& _tr;
110   public:
111     Mark(BranchTracker& tr, bool has_branch_here)
112       : _tr(tr)  { _tr.push(has_branch_here); }
113     ~Mark() { _tr.pop(); }
114   };
115 
116 }; // end: BranchTracker
117 
118 struct LoadedClassInfo : public ResourceObj {
119 public:
120   LoadedClassInfo* _next;
121   Klass* const _klass;
122   const ClassLoaderData* const _cld;
123 
124   LoadedClassInfo(Klass* klass, const ClassLoaderData* cld)
125     : _klass(klass), _cld(cld) {}
126 
127 };
128 
129 class LoaderTreeNode : public ResourceObj {
130 
131   // We walk the CLDG and, for each CLD which is non-unsafe_anonymous, add
132   // a tree node.
133   // To add a node we need its parent node; if the parent node does not yet
134   // exist - because we have not yet encountered the CLD for the parent loader -
135   // we add a preliminary empty LoaderTreeNode for it. This preliminary node
136   // just contains the loader oop and nothing else. Once we encounter the CLD of
137   // this parent loader, we fill in all the other details.
138 
139   const oop _loader_oop;
140   const ClassLoaderData* _cld;
141 
142   LoaderTreeNode* _child;
143   LoaderTreeNode* _next;
144 
145   LoadedClassInfo* _classes;
146   int _num_classes;
147 
148   LoadedClassInfo* _anon_classes;
149   int _num_anon_classes;
150 
151   // In default view, similar tree nodes (same loader class, same name or no name)
152   // are folded into each other to make the output more readable.
153   // _num_folded contains the number of nodes which have been folded into this
154   // one.
155   int _num_folded;
156 
157   void print_with_childs(outputStream* st, BranchTracker& branchtracker,
158       bool print_classes, bool verbose) const {
159 
160     ResourceMark rm;
161 
162     if (_cld == NULL) {
163       // Not sure how this could happen: we added a preliminary node for a parent but then never encountered
164       // its CLD?
165       return;
166     }
167 
168     // Retrieve information.
169     const Klass* const loader_klass = _cld->class_loader_klass();
170     const Symbol* const loader_name = _cld->name();
171 
172     branchtracker.print(st);
173 
174     // e.g. "+--- jdk.internal.reflect.DelegatingClassLoader"
175     st->print("+%.*s", BranchTracker::twig_len, "----------");
176     if (_cld->is_the_null_class_loader_data()) {
177       st->print(" <bootstrap>");
178     } else {
179       if (loader_name != NULL) {
180         st->print(" \"%s\",", loader_name->as_C_string());
181       }
182       st->print(" %s", loader_klass != NULL ? loader_klass->external_name() : "??");
183       if (_num_folded > 0) {
184         st->print(" (+ %d more)", _num_folded);
185       }
186     }
187     st->cr();
188 
189     // Output following this node (node details and child nodes) - up to the next sibling node
190     // needs to be prefixed with "|" if there is a follow up sibling.
191     const bool have_sibling = _next != NULL;
192     BranchTracker::Mark trm(branchtracker, have_sibling);
193 
194     {
195       // optional node details following this node needs to be prefixed with "|"
196       // if there are follow up child nodes.
197       const bool have_child = _child != NULL;
198       BranchTracker::Mark trm(branchtracker, have_child);
199 
200       // Empty line
201       branchtracker.print(st);
202       st->cr();
203 
204       const int indentation = 18;
205 
206       if (verbose) {
207         branchtracker.print(st);
208         st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Oop:", p2i(_loader_oop));
209         branchtracker.print(st);
210         st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Data:", p2i(_cld));
211         branchtracker.print(st);
212         st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Klass:", p2i(loader_klass));
213 
214         // Empty line
215         branchtracker.print(st);
216         st->cr();
217       }
218 
219       if (print_classes) {
220         if (_classes != NULL) {
221           for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next) {
222             // Non-unsafe anonymous classes should live in the primary CLD of its loader
223             assert(lci->_cld == _cld, "must be");
224 
225             branchtracker.print(st);
226             if (lci == _classes) { // first iteration
227               st->print("%*s ", indentation, "Classes:");
228             } else {
229               st->print("%*s ", indentation, "");
230             }
231             st->print("%s", lci->_klass->external_name());
232 
233             // Special treatment for generated core reflection accessor classes: print invocation target.
234             if (ReflectionAccessorImplKlassHelper::is_generated_accessor(lci->_klass)) {
235               st->print(" (invokes: ");
236               ReflectionAccessorImplKlassHelper::print_invocation_target(st, lci->_klass);
237               st->print(")");
238             }
239 
240             st->cr();
241           }
242           branchtracker.print(st);
243           st->print("%*s ", indentation, "");
244           st->print_cr("(%u class%s)", _num_classes, (_num_classes == 1) ? "" : "es");
245 
246           // Empty line
247           branchtracker.print(st);
248           st->cr();
249         }
250 
251         if (_anon_classes != NULL) {
252           for (LoadedClassInfo* lci = _anon_classes; lci; lci = lci->_next) {
253             branchtracker.print(st);
254             if (lci == _anon_classes) { // first iteration
255               st->print("%*s ", indentation, "Unsafe Anonymous Classes:");
256             } else {
257               st->print("%*s ", indentation, "");
258             }
259             st->print("%s", lci->_klass->external_name());
260             // For unsafe anonymous classes, also print CLD if verbose. Should be a different one than the primary CLD.
261             assert(lci->_cld != _cld, "must be");
262             if (verbose) {
263               st->print("  (Loader Data: " PTR_FORMAT ")", p2i(lci->_cld));
264             }
265             st->cr();
266           }
267           branchtracker.print(st);
268           st->print("%*s ", indentation, "");
269           st->print_cr("(%u unsafe anonymous class%s)", _num_anon_classes, (_num_anon_classes == 1) ? "" : "es");
270 
271           // Empty line
272           branchtracker.print(st);
273           st->cr();
274         }
275 
276       } // end: print_classes
277 
278     } // Pop branchtracker mark
279 
280     // Print children, recursively
281     LoaderTreeNode* c = _child;
282     while (c != NULL) {
283       c->print_with_childs(st, branchtracker, print_classes, verbose);
284       c = c->_next;
285     }
286 
287   }
288 
289   // Helper: Attempt to fold this node into the target node. If success, returns true.
290   // Folding can be done if both nodes are leaf nodes and they refer to the same loader class
291   // and they have the same name or no name (note: leaf check is done by caller).
292   bool can_fold_into(LoaderTreeNode* target_node) const {
293     assert(is_leaf() && target_node->is_leaf(), "must be leaf");
294     return _cld->class_loader_klass() == target_node->_cld->class_loader_klass() &&
295            _cld->name() == target_node->_cld->name();
296   }
297 
298 public:
299 
300   LoaderTreeNode(const oop loader_oop)
301     : _loader_oop(loader_oop), _cld(NULL), _child(NULL), _next(NULL),
302       _classes(NULL), _num_classes(0), _anon_classes(NULL), _num_anon_classes(0),
303       _num_folded(0)
304     {}
305 
306   void set_cld(const ClassLoaderData* cld) {
307     _cld = cld;
308   }
309 
310   void add_child(LoaderTreeNode* info) {
311     info->_next = _child;
312     _child = info;
313   }
314 
315   void add_sibling(LoaderTreeNode* info) {
316     assert(info->_next == NULL, "must be");
317     info->_next = _next;
318     _next = info;
319   }
320 
321   void add_classes(LoadedClassInfo* first_class, int num_classes, bool is_unsafe_anonymous) {
322     LoadedClassInfo** p_list_to_add_to = is_unsafe_anonymous ? &_anon_classes : &_classes;
323     // Search tail.
324     while ((*p_list_to_add_to) != NULL) {
325       p_list_to_add_to = &(*p_list_to_add_to)->_next;
326     }
327     *p_list_to_add_to = first_class;
328     if (is_unsafe_anonymous) {
329       _num_anon_classes += num_classes;
330     } else {
331       _num_classes += num_classes;
332     }
333   }
334 
335   const ClassLoaderData* cld() const {
336     return _cld;
337   }
338 
339   const oop loader_oop() const {
340     return _loader_oop;
341   }
342 
343   LoaderTreeNode* find(const oop loader_oop) {
344     LoaderTreeNode* result = NULL;
345     if (_loader_oop == loader_oop) {
346       result = this;
347     } else {
348       LoaderTreeNode* c = _child;
349       while (c != NULL && result == NULL) {
350         result = c->find(loader_oop);
351         c = c->_next;
352       }
353     }
354     return result;
355   }
356 
357   bool is_leaf() const { return _child == NULL; }
358 
359   // Attempt to fold similar nodes among this node's children. We only fold leaf nodes
360   // (no child class loaders).
361   // For non-leaf nodes (class loaders with child class loaders), do this recursivly.
362   void fold_children() {
363     LoaderTreeNode* node = _child;
364     LoaderTreeNode* prev = NULL;
365     while (node != NULL) {
366       LoaderTreeNode* matching_node = NULL;
367       if (node->is_leaf()) {
368         // Look among the preceeding node siblings for a match.
369         for (LoaderTreeNode* node2 = _child; node2 != node && matching_node == NULL;
370             node2 = node2->_next) {
371           if (node2->is_leaf() && node->can_fold_into(node2)) {
372             matching_node = node2;
373           }
374         }
375       } else {
376         node->fold_children();
377       }
378       if (matching_node != NULL) {
379         // Increase fold count for the matching node and remove folded node from the child list.
380         matching_node->_num_folded ++;
381         assert(prev != NULL, "Sanity"); // can never happen since we do not fold the first node.
382         prev->_next = node->_next;
383       } else {
384         prev = node;
385       }
386       node = node->_next;
387     }
388   }
389 
390   void print_with_childs(outputStream* st, bool print_classes, bool print_add_info) const {
391     BranchTracker bwt;
392     print_with_childs(st, bwt, print_classes, print_add_info);
393   }
394 
395 };
396 
397 class LoadedClassCollectClosure : public KlassClosure {
398 public:
399   LoadedClassInfo* _list;
400   const ClassLoaderData* _cld;
401   int _num_classes;
402   LoadedClassCollectClosure(const ClassLoaderData* cld)
403     : _list(NULL), _cld(cld), _num_classes(0) {}
404   void do_klass(Klass* k) {
405     LoadedClassInfo* lki = new LoadedClassInfo(k, _cld);
406     lki->_next = _list;
407     _list = lki;
408     _num_classes ++;
409   }
410 };
411 
412 class LoaderInfoScanClosure : public CLDClosure {
413 
414   const bool _print_classes;
415   const bool _verbose;
416   LoaderTreeNode* _root;
417 
418   static void fill_in_classes(LoaderTreeNode* info, const ClassLoaderData* cld) {
419     assert(info != NULL && cld != NULL, "must be");
420     LoadedClassCollectClosure lccc(cld);
421     const_cast<ClassLoaderData*>(cld)->classes_do(&lccc);
422     if (lccc._num_classes > 0) {
423       info->add_classes(lccc._list, lccc._num_classes, cld->is_unsafe_anonymous());
424     }
425   }
426 
427   LoaderTreeNode* find_node_or_add_empty_node(oop loader_oop) {
428 
429     assert(_root != NULL, "root node must exist");
430 
431     if (loader_oop == NULL) {
432       return _root;
433     }
434 
435     // Check if a node for this oop already exists.
436     LoaderTreeNode* info = _root->find(loader_oop);
437 
438     if (info == NULL) {
439       // It does not. Create a node.
440       info = new LoaderTreeNode(loader_oop);
441 
442       // Add it to tree.
443       LoaderTreeNode* parent_info = NULL;
444 
445       // Recursively add parent nodes if needed.
446       const oop parent_oop = java_lang_ClassLoader::parent(loader_oop);
447       if (parent_oop == NULL) {
448         parent_info = _root;
449       } else {
450         parent_info = find_node_or_add_empty_node(parent_oop);
451       }
452       assert(parent_info != NULL, "must be");
453 
454       parent_info->add_child(info);
455     }
456     return info;
457   }
458 
459 
460 public:
461   LoaderInfoScanClosure(bool print_classes, bool verbose)
462     : _print_classes(print_classes), _verbose(verbose), _root(NULL) {
463     _root = new LoaderTreeNode(NULL);
464   }
465 
466   void print_results(outputStream* st) const {
467     _root->print_with_childs(st, _print_classes, _verbose);
468   }
469 
470   void do_cld (ClassLoaderData* cld) {
471 
472     // We do not display unloading loaders, for now.
473     if (!cld->is_alive()) {
474       return;
475     }
476 
477     const oop loader_oop = cld->class_loader();
478 
479     LoaderTreeNode* info = find_node_or_add_empty_node(loader_oop);
480     assert(info != NULL, "must be");
481 
482     // Update CLD in node, but only if this is the primary CLD for this loader.
483     if (cld->is_unsafe_anonymous() == false) {
484       assert(info->cld() == NULL, "there should be only one primary CLD per loader");
485       info->set_cld(cld);
486     }
487 
488     // Add classes.
489     fill_in_classes(info, cld);
490   }
491 
492   void fold() {
493     _root->fold_children();
494   }
495 
496 };
497 
498 
499 class ClassLoaderHierarchyVMOperation : public VM_Operation {
500   outputStream* const _out;
501   const bool _show_classes;
502   const bool _verbose;
503   const bool _fold;
504 public:
505   ClassLoaderHierarchyVMOperation(outputStream* out, bool show_classes, bool verbose, bool fold) :
506     _out(out), _show_classes(show_classes), _verbose(verbose), _fold(fold)
507   {}
508 
509   VMOp_Type type() const {
510     return VMOp_ClassLoaderHierarchyOperation;
511   }
512 
513   void doit() {
514     assert(SafepointSynchronize::is_at_safepoint(), "must be a safepoint");
515     ResourceMark rm;
516     LoaderInfoScanClosure cl (_show_classes, _verbose);
517     ClassLoaderDataGraph::cld_do(&cl);
518     // In non-verbose and non-show-classes mode, attempt to fold the tree.
519     if (_fold) {
520       if (!_verbose && !_show_classes) {
521         cl.fold();
522       }
523     }
524     cl.print_results(_out);
525   }
526 };
527 
528 // This command needs to be executed at a safepoint.
529 void ClassLoaderHierarchyDCmd::execute(DCmdSource source, TRAPS) {
530   ClassLoaderHierarchyVMOperation op(output(), _show_classes.value(), _verbose.value(), _fold.value());
531   VMThread::execute(&op);
532 }