< prev index next >
src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp
Print this page
rev 50411 : imported patch 8203682-jcmd-print-classloader-hierarchy
rev 50412 : [mq]: 8203682-jcmd-print-classloader-hierarchy-delta
@@ -27,10 +27,11 @@
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderHierarchyDCmd.hpp"
#include "memory/allocation.hpp"
#include "memory/resourceArea.hpp"
+#include "runtime/safepoint.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/ostream.hpp"
ClassLoaderHierarchyDCmd::ClassLoaderHierarchyDCmd(outputStream* output, bool heap)
@@ -53,11 +54,11 @@
return 0;
}
}
// Helper class for drawing the branches to the left of a node.
-class BranchTracker {
+class BranchTracker : public StackObj {
// "<x>"
// " |---<y>"
// " | |
// " | <z>"
// " | |---<z1>
@@ -111,11 +112,11 @@
~Mark() { _tr.pop(); }
};
}; // end: BranchTracker
-struct LoadedClassInfo : public CHeapObj<mtInternal> {
+struct LoadedClassInfo : public ResourceObj {
public:
LoadedClassInfo* _next;
Klass* const _klass;
const ClassLoaderData* const _cld;
@@ -123,11 +124,17 @@
: _klass(klass), _cld(cld)
{}
};
-class LoaderTreeNode : public CHeapObj<mtInternal> {
+class LoaderTreeNode : public ResourceObj {
+
+ // We walk the CLDG and, for each CLD which is non-anonymous, add
+ // a tree node. To add a node we need its parent node; if it itself
+ // does not exist yet, we add a preliminary node for it. This preliminary
+ // node just contains its loader oop; later, when encountering its CLD in
+ // our CLDG walk, we complete the missing information in this node.
const oop _loader_oop;
const ClassLoaderData* _cld;
LoaderTreeNode* _child;
@@ -142,65 +149,57 @@
void print_with_childs(outputStream* st, BranchTracker& branchtracker,
bool print_classes, bool verbose) const
{
ResourceMark rm;
- // Retrieve information.
- const Klass* loader_klass = NULL;
- const char* loader_name = NULL;
- const char* loader_class_name = NULL;
-
- if (_loader_oop != NULL) {
- loader_klass = _loader_oop->klass();
- if (loader_klass != NULL) {
- loader_class_name = loader_klass->external_name();
- }
- oop nameOop = java_lang_ClassLoader::name(_loader_oop);
- if (nameOop != NULL) {
- const char* s = java_lang_String::as_utf8_string(nameOop);
- if (s != NULL) {
- loader_name = s;
- }
- }
- } else {
- // Boot loader
- loader_name = "<bootstrap>";
+ if (_cld == NULL) {
+ // Not sure how this could happen: we added a preliminary node for a parent but then never encountered
+ // its CLD?
+ return;
}
+ // Retrieve information.
+ const Klass* const loader_klass = _cld->class_loader_klass();
+ const Symbol* const loader_name = _cld->class_loader_name();
+
branchtracker.print(st);
- // e.g. "+--- ABC (instance of DEF)"
- st->print("+%.*s ", BranchTracker::twiglen, "----------");
- st->print("%s", loader_name != NULL ? loader_name : "<unnamed>");
- if (loader_class_name != NULL) {
- st->print(" (instance of %s)", loader_class_name);
+ // e.g. "+--- jdk.internal.reflect.DelegatingClassLoader"
+ st->print("+%.*s", BranchTracker::twiglen, "----------");
+ if (_cld->is_the_null_class_loader_data()) {
+ st->print(" <bootstrap>");
+ } else {
+ if (loader_name != NULL) {
+ st->print(" \"%s\",", loader_name->as_C_string());
+ }
+ st->print(" %s", loader_klass != NULL ? loader_klass->external_name() : "??");
+ st->print(" {" PTR_FORMAT "}", p2i(_loader_oop));
}
st->cr();
+ // Output following this node (node details and child nodes) - up to the next sibling node
+ // needs to be prefixed with "|" if there is a follow up sibling.
const bool have_sibling = _next != NULL;
BranchTracker::Mark trm(branchtracker, have_sibling);
- // Area below class loader name, but not belonging to child nodes. Here
- // we print additional infos about the loader (e..g. loaded classes).
-
{
+ // optional node details following this node needs to be prefixed with "|"
+ // if there are follow up child nodes.
const bool have_child = _child != NULL;
BranchTracker::Mark trm(branchtracker, have_child);
// Empty line
branchtracker.print(st);
st->cr();
- const int indentation = 22;
+ const int indentation = 18;
if (verbose) {
branchtracker.print(st);
- st->print_cr("%*s " PTR_FORMAT, indentation, "CLD:", p2i(_cld));
+ st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Data:", p2i(_cld));
branchtracker.print(st);
st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Klass:", p2i(loader_klass));
- branchtracker.print(st);
- st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Oop:", p2i(_loader_oop));
// Empty line
branchtracker.print(st);
st->cr();
}
@@ -245,11 +244,11 @@
}
st->cr();
}
branchtracker.print(st);
st->print("%*s ", indentation, "");
- st->print_cr("(%u anononymous class%s)", _num_anon_classes, (_num_anon_classes == 1) ? "" : "es");
+ st->print_cr("(%u anonymous class%s)", _num_anon_classes, (_num_anon_classes == 1) ? "" : "es");
// Empty line
branchtracker.print(st);
st->cr();
}
@@ -265,43 +264,19 @@
c = c->_next;
}
}
- void free_child_nodes() {
- LoaderTreeNode* c = _child;
- while (c) {
- LoaderTreeNode* next = c->_next;
- delete c;
- c = next;
- }
- }
-
- void free_class_info_list(LoadedClassInfo* first) {
- LoadedClassInfo* p = first;
- while (p) {
- LoadedClassInfo* next = p->_next;
- delete p;
- p = next;
- }
- }
-
public:
LoaderTreeNode(const oop loader_oop)
: _loader_oop(loader_oop), _cld(NULL)
, _child(NULL), _next(NULL)
, _classes(NULL), _anon_classes(NULL)
, _num_classes(0), _num_anon_classes(0)
{}
- ~LoaderTreeNode() {
- free_child_nodes();
- free_class_info_list(_classes);
- free_class_info_list(_anon_classes);
- }
-
void set_cld(const ClassLoaderData* cld) { _cld = cld; }
void add_child(LoaderTreeNode* info) {
info->_next = _child;
_child = info;
@@ -357,11 +332,10 @@
const ClassLoaderData* _cld;
int _num_classes;
LoadedClassCollectClosure(const ClassLoaderData* cld)
: _list(NULL), _cld(cld), _num_classes(0) {}
void do_klass(Klass* k) {
- ResourceMark rm;
LoadedClassInfo* lki = new LoadedClassInfo(k, _cld);
lki->_next = _list;
_list = lki;
_num_classes ++;
}
@@ -420,14 +394,10 @@
: _print_classes(print_classes), _verbose(verbose), _root(NULL)
{
_root = new LoaderTreeNode(NULL);
}
- ~LoaderInfoScanClosure() {
- delete _root;
- }
-
void print_results(outputStream* st) const {
_root->print_with_childs(st, _print_classes, _verbose);
}
void do_cld (ClassLoaderData* cld) {
@@ -467,18 +437,18 @@
VMOp_Type type() const {
return VMOp_ClassLoaderHierarchyOperation;
}
void doit() {
+ assert(SafepointSynchronize::is_at_safepoint(), "must be a safepoint");
+ ResourceMark rm;
LoaderInfoScanClosure cl (_show_classes, _verbose);
ClassLoaderDataGraph::cld_do(&cl);
cl.print_results(_out);
}
-
};
-
-
+// This command needs to be executed at a safepoint.
void ClassLoaderHierarchyDCmd::execute(DCmdSource source, TRAPS) {
ClassLoaderHierarchyVMOperation op(output(), _show_classes.value(), _verbose.value());
VMThread::execute(&op);
}
< prev index next >