Bug Summary

File:jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp
Warning:line 319, column 10
Value stored to 'is_hidden' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name classLoaderHierarchyDCmd.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/precompiled -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D _GNU_SOURCE -D _REENTRANT -D LIBC=gnu -D LINUX -D VM_LITTLE_ENDIAN -D _LP64=1 -D ASSERT -D CHECK_UNHANDLED_OOPS -D TARGET_ARCH_x86 -D INCLUDE_SUFFIX_OS=_linux -D INCLUDE_SUFFIX_CPU=_x86 -D INCLUDE_SUFFIX_COMPILER=_gcc -D TARGET_COMPILER_gcc -D AMD64 -D HOTSPOT_LIB_ARCH="amd64" -D COMPILER1 -D COMPILER2 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -I /home/daniel/Projects/java/jdk/src/hotspot/share/precompiled -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjimage -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-format-zero-length -Wno-unused-parameter -Wno-unused -Wno-parentheses -Wno-comment -Wno-unknown-pragmas -Wno-address -Wno-delete-non-virtual-dtor -Wno-char-subscripts -Wno-array-bounds -Wno-int-in-bool-context -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-empty-body -Wno-strict-overflow -Wno-sequence-point -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-cast-function-type -Wno-shift-negative-value -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make/hotspot -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fno-rtti -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp
1/*
2 * Copyright (c) 2018, 2021, 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 "utilities/globalDefinitions.hpp"
35#include "utilities/ostream.hpp"
36
37
38ClassLoaderHierarchyDCmd::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
49int ClassLoaderHierarchyDCmd::num_arguments() {
50 ResourceMark rm;
51 ClassLoaderHierarchyDCmd* dcmd = new ClassLoaderHierarchyDCmd(NULL__null, false);
52 if (dcmd != NULL__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.
61class 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
77public:
78
79 enum { max_depth = 64, twig_len = 2, branch_spacing = 5 };
80
81private:
82
83 char _branches[max_depth];
84 int _pos;
85
86public:
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")do { if (!(_pos > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 98, "assert(" "_pos > 0" ") failed", "must be"); ::breakpoint
(); } } while (0)
;
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
118struct LoadedClassInfo : public ResourceObj {
119public:
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
129class LoaderTreeNode : public ResourceObj {
130
131 // We walk the CLDG and, for each CLD which is findable, 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* _hidden_classes;
149 int _num_hidden_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__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. +-- "app", jdk.internal.loader.ClassLoaders$AppClassLoader
175 st->print("+%.*s", BranchTracker::twig_len, "----------");
176 if (_cld->is_the_null_class_loader_data()) {
177 st->print(" <bootstrap>");
178 } else {
179 assert(!_cld->has_class_mirror_holder(), "_cld must be the primary cld")do { if (!(!_cld->has_class_mirror_holder())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 179, "assert(" "!_cld->has_class_mirror_holder()" ") failed"
, "_cld must be the primary cld"); ::breakpoint(); } } while (
0)
;
180 if (loader_name != NULL__null) {
181 st->print(" \"%s\",", loader_name->as_C_string());
182 }
183 st->print(" %s", loader_klass != NULL__null ? loader_klass->external_name() : "??");
184 if (_num_folded > 0) {
185 st->print(" (+ %d more)", _num_folded);
186 }
187 }
188 st->cr();
189
190 // Output following this node (node details and child nodes) - up to the next sibling node
191 // needs to be prefixed with "|" if there is a follow up sibling.
192 const bool have_sibling = _next != NULL__null;
193 BranchTracker::Mark trm(branchtracker, have_sibling);
194
195 {
196 // optional node details following this node needs to be prefixed with "|"
197 // if there are follow up child nodes.
198 const bool have_child = _child != NULL__null;
199 BranchTracker::Mark trm(branchtracker, have_child);
200
201 // Empty line
202 branchtracker.print(st);
203 st->cr();
204
205 const int indentation = 18;
206
207 if (verbose) {
208 branchtracker.print(st);
209 st->print_cr("%*s " PTR_FORMAT"0x%016" "l" "x", indentation, "Loader Oop:", p2i(_loader_oop));
210 branchtracker.print(st);
211 st->print_cr("%*s " PTR_FORMAT"0x%016" "l" "x", indentation, "Loader Data:", p2i(_cld));
212 branchtracker.print(st);
213 st->print_cr("%*s " PTR_FORMAT"0x%016" "l" "x", indentation, "Loader Klass:", p2i(loader_klass));
214
215 // Empty line
216 branchtracker.print(st);
217 st->cr();
218 }
219
220 if (print_classes) {
221 if (_classes != NULL__null) {
222 for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next) {
223 // non-strong hidden classes should not live in
224 // the primary CLD of their loaders.
225 assert(lci->_cld == _cld, "must be")do { if (!(lci->_cld == _cld)) { (*g_assert_poison) = 'X';
; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 225, "assert(" "lci->_cld == _cld" ") failed", "must be"
); ::breakpoint(); } } while (0)
;
226
227 branchtracker.print(st);
228 if (lci == _classes) { // first iteration
229 st->print("%*s ", indentation, "Classes:");
230 } else {
231 st->print("%*s ", indentation, "");
232 }
233 st->print("%s", lci->_klass->external_name());
234 st->cr();
235 }
236 branchtracker.print(st);
237 st->print("%*s ", indentation, "");
238 st->print_cr("(%u class%s)", _num_classes, (_num_classes == 1) ? "" : "es");
239
240 // Empty line
241 branchtracker.print(st);
242 st->cr();
243 }
244
245 if (_hidden_classes != NULL__null) {
246 for (LoadedClassInfo* lci = _hidden_classes; lci; lci = lci->_next) {
247 branchtracker.print(st);
248 if (lci == _hidden_classes) { // first iteration
249 st->print("%*s ", indentation, "Hidden Classes:");
250 } else {
251 st->print("%*s ", indentation, "");
252 }
253 st->print("%s", lci->_klass->external_name());
254 // For non-strong hidden classes, also print CLD if verbose. Should be a
255 // different one than the primary CLD.
256 assert(lci->_cld != _cld, "must be")do { if (!(lci->_cld != _cld)) { (*g_assert_poison) = 'X';
; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 256, "assert(" "lci->_cld != _cld" ") failed", "must be"
); ::breakpoint(); } } while (0)
;
257 if (verbose) {
258 st->print(" (Loader Data: " PTR_FORMAT"0x%016" "l" "x" ")", p2i(lci->_cld));
259 }
260 st->cr();
261 }
262 branchtracker.print(st);
263 st->print("%*s ", indentation, "");
264 st->print_cr("(%u hidden class%s)", _num_hidden_classes,
265 (_num_hidden_classes == 1) ? "" : "es");
266
267 // Empty line
268 branchtracker.print(st);
269 st->cr();
270 }
271
272 } // end: print_classes
273
274 } // Pop branchtracker mark
275
276 // Print children, recursively
277 LoaderTreeNode* c = _child;
278 while (c != NULL__null) {
279 c->print_with_childs(st, branchtracker, print_classes, verbose);
280 c = c->_next;
281 }
282
283 }
284
285 // Helper: Attempt to fold this node into the target node. If success, returns true.
286 // Folding can be done if both nodes are leaf nodes and they refer to the same loader class
287 // and they have the same name or no name (note: leaf check is done by caller).
288 bool can_fold_into(LoaderTreeNode* target_node) const {
289 assert(is_leaf() && target_node->is_leaf(), "must be leaf")do { if (!(is_leaf() && target_node->is_leaf())) {
(*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 289, "assert(" "is_leaf() && target_node->is_leaf()"
") failed", "must be leaf"); ::breakpoint(); } } while (0)
;
290 return _cld->class_loader_klass() == target_node->_cld->class_loader_klass() &&
291 _cld->name() == target_node->_cld->name();
292 }
293
294public:
295
296 LoaderTreeNode(const oop loader_oop)
297 : _loader_oop(loader_oop), _cld(NULL__null), _child(NULL__null), _next(NULL__null),
298 _classes(NULL__null), _num_classes(0), _hidden_classes(NULL__null),
299 _num_hidden_classes(0), _num_folded(0)
300 {}
301
302 void set_cld(const ClassLoaderData* cld) {
303 _cld = cld;
304 }
305
306 void add_child(LoaderTreeNode* info) {
307 info->_next = _child;
308 _child = info;
309 }
310
311 void add_sibling(LoaderTreeNode* info) {
312 assert(info->_next == NULL, "must be")do { if (!(info->_next == __null)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 312, "assert(" "info->_next == __null" ") failed", "must be"
); ::breakpoint(); } } while (0)
;
313 info->_next = _next;
314 _next = info;
315 }
316
317 void add_classes(LoadedClassInfo* first_class, int num_classes, bool has_class_mirror_holder) {
318 LoadedClassInfo** p_list_to_add_to;
319 bool is_hidden = first_class->_klass->is_hidden();
Value stored to 'is_hidden' during its initialization is never read
320 if (has_class_mirror_holder) {
321 p_list_to_add_to = &_hidden_classes;
322 } else {
323 p_list_to_add_to = &_classes;
324 }
325 // Search tail.
326 while ((*p_list_to_add_to) != NULL__null) {
327 p_list_to_add_to = &(*p_list_to_add_to)->_next;
328 }
329 *p_list_to_add_to = first_class;
330 if (has_class_mirror_holder) {
331 _num_hidden_classes += num_classes;
332 } else {
333 _num_classes += num_classes;
334 }
335 }
336
337 const ClassLoaderData* cld() const {
338 return _cld;
339 }
340
341 const oop loader_oop() const {
342 return _loader_oop;
343 }
344
345 LoaderTreeNode* find(const oop loader_oop) {
346 LoaderTreeNode* result = NULL__null;
347 if (_loader_oop == loader_oop) {
348 result = this;
349 } else {
350 LoaderTreeNode* c = _child;
351 while (c != NULL__null && result == NULL__null) {
352 result = c->find(loader_oop);
353 c = c->_next;
354 }
355 }
356 return result;
357 }
358
359 bool is_leaf() const { return _child == NULL__null; }
360
361 // Attempt to fold similar nodes among this node's children. We only fold leaf nodes
362 // (no child class loaders).
363 // For non-leaf nodes (class loaders with child class loaders), do this recursivly.
364 void fold_children() {
365 LoaderTreeNode* node = _child;
366 LoaderTreeNode* prev = NULL__null;
367 while (node != NULL__null) {
368 LoaderTreeNode* matching_node = NULL__null;
369 if (node->is_leaf()) {
370 // Look among the preceeding node siblings for a match.
371 for (LoaderTreeNode* node2 = _child; node2 != node && matching_node == NULL__null;
372 node2 = node2->_next) {
373 if (node2->is_leaf() && node->can_fold_into(node2)) {
374 matching_node = node2;
375 }
376 }
377 } else {
378 node->fold_children();
379 }
380 if (matching_node != NULL__null) {
381 // Increase fold count for the matching node and remove folded node from the child list.
382 matching_node->_num_folded ++;
383 assert(prev != NULL, "Sanity")do { if (!(prev != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 383, "assert(" "prev != __null" ") failed", "Sanity"); ::breakpoint
(); } } while (0)
; // can never happen since we do not fold the first node.
384 prev->_next = node->_next;
385 } else {
386 prev = node;
387 }
388 node = node->_next;
389 }
390 }
391
392 void print_with_childs(outputStream* st, bool print_classes, bool print_add_info) const {
393 BranchTracker bwt;
394 print_with_childs(st, bwt, print_classes, print_add_info);
395 }
396
397};
398
399class LoadedClassCollectClosure : public KlassClosure {
400public:
401 LoadedClassInfo* _list;
402 const ClassLoaderData* _cld;
403 int _num_classes;
404 LoadedClassCollectClosure(const ClassLoaderData* cld)
405 : _list(NULL__null), _cld(cld), _num_classes(0) {}
406 void do_klass(Klass* k) {
407 LoadedClassInfo* lki = new LoadedClassInfo(k, _cld);
408 lki->_next = _list;
409 _list = lki;
410 _num_classes ++;
411 }
412};
413
414class LoaderInfoScanClosure : public CLDClosure {
415
416 const bool _print_classes;
417 const bool _verbose;
418 LoaderTreeNode* _root;
419
420 static void fill_in_classes(LoaderTreeNode* info, const ClassLoaderData* cld) {
421 assert(info != NULL && cld != NULL, "must be")do { if (!(info != __null && cld != __null)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 421, "assert(" "info != __null && cld != __null" ") failed"
, "must be"); ::breakpoint(); } } while (0)
;
422 LoadedClassCollectClosure lccc(cld);
423 const_cast<ClassLoaderData*>(cld)->classes_do(&lccc);
424 if (lccc._num_classes > 0) {
425 info->add_classes(lccc._list, lccc._num_classes, cld->has_class_mirror_holder());
426 }
427 }
428
429 LoaderTreeNode* find_node_or_add_empty_node(oop loader_oop) {
430
431 assert(_root != NULL, "root node must exist")do { if (!(_root != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 431, "assert(" "_root != __null" ") failed", "root node must exist"
); ::breakpoint(); } } while (0)
;
432
433 if (loader_oop == NULL__null) {
434 return _root;
435 }
436
437 // Check if a node for this oop already exists.
438 LoaderTreeNode* info = _root->find(loader_oop);
439
440 if (info == NULL__null) {
441 // It does not. Create a node.
442 info = new LoaderTreeNode(loader_oop);
443
444 // Add it to tree.
445 LoaderTreeNode* parent_info = NULL__null;
446
447 // Recursively add parent nodes if needed.
448 const oop parent_oop = java_lang_ClassLoader::parent(loader_oop);
449 if (parent_oop == NULL__null) {
450 parent_info = _root;
451 } else {
452 parent_info = find_node_or_add_empty_node(parent_oop);
453 }
454 assert(parent_info != NULL, "must be")do { if (!(parent_info != __null)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 454, "assert(" "parent_info != __null" ") failed", "must be"
); ::breakpoint(); } } while (0)
;
455
456 parent_info->add_child(info);
457 }
458 return info;
459 }
460
461
462public:
463 LoaderInfoScanClosure(bool print_classes, bool verbose)
464 : _print_classes(print_classes), _verbose(verbose), _root(NULL__null) {
465 _root = new LoaderTreeNode(NULL__null);
466 }
467
468 void print_results(outputStream* st) const {
469 _root->print_with_childs(st, _print_classes, _verbose);
470 }
471
472 void do_cld (ClassLoaderData* cld) {
473
474 // We do not display unloading loaders, for now.
475 if (!cld->is_alive()) {
476 return;
477 }
478
479 const oop loader_oop = cld->class_loader();
480
481 LoaderTreeNode* info = find_node_or_add_empty_node(loader_oop);
482 assert(info != NULL, "must be")do { if (!(info != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 482, "assert(" "info != __null" ") failed", "must be"); ::breakpoint
(); } } while (0)
;
483
484 // Update CLD in node, but only if this is the primary CLD for this loader.
485 if (cld->has_class_mirror_holder() == false) {
486 assert(info->cld() == NULL, "there should be only one primary CLD per loader")do { if (!(info->cld() == __null)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 486, "assert(" "info->cld() == __null" ") failed", "there should be only one primary CLD per loader"
); ::breakpoint(); } } while (0)
;
487 info->set_cld(cld);
488 }
489
490 // Add classes.
491 fill_in_classes(info, cld);
492 }
493
494 void fold() {
495 _root->fold_children();
496 }
497
498};
499
500
501class ClassLoaderHierarchyVMOperation : public VM_Operation {
502 outputStream* const _out;
503 const bool _show_classes;
504 const bool _verbose;
505 const bool _fold;
506public:
507 ClassLoaderHierarchyVMOperation(outputStream* out, bool show_classes, bool verbose, bool fold) :
508 _out(out), _show_classes(show_classes), _verbose(verbose), _fold(fold)
509 {}
510
511 VMOp_Type type() const {
512 return VMOp_ClassLoaderHierarchyOperation;
513 }
514
515 void doit() {
516 assert(SafepointSynchronize::is_at_safepoint(), "must be a safepoint")do { if (!(SafepointSynchronize::is_at_safepoint())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp"
, 516, "assert(" "SafepointSynchronize::is_at_safepoint()" ") failed"
, "must be a safepoint"); ::breakpoint(); } } while (0)
;
517 ResourceMark rm;
518 LoaderInfoScanClosure cl (_show_classes, _verbose);
519 ClassLoaderDataGraph::loaded_cld_do(&cl);
520 // In non-verbose and non-show-classes mode, attempt to fold the tree.
521 if (_fold) {
522 if (!_verbose && !_show_classes) {
523 cl.fold();
524 }
525 }
526 cl.print_results(_out);
527 }
528};
529
530// This command needs to be executed at a safepoint.
531void ClassLoaderHierarchyDCmd::execute(DCmdSource source, TRAPSJavaThread* __the_thread__) {
532 ClassLoaderHierarchyVMOperation op(output(), _show_classes.value(), _verbose.value(), _fold.value());
533 VMThread::execute(&op);
534}