1 /*
2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #include "precompiled.hpp"
26 #include "classfile/classLoaderData.inline.hpp"
27 #include "classfile/classLoaderDataGraph.hpp"
28 #include "classfile/classLoaderStats.hpp"
29 #include "oops/oop.inline.hpp"
30 #include "utilities/globalDefinitions.hpp"
31 
32 
33 class ClassStatsClosure : public KlassClosure {
34 public:
35   int _num_classes;
36 
ClassStatsClosure()37   ClassStatsClosure() :
38     _num_classes(0) {
39   }
40 
do_klass(Klass * k)41   virtual void do_klass(Klass* k) {
42     _num_classes++;
43   }
44 };
45 
46 
do_cld(ClassLoaderData * cld)47 void ClassLoaderStatsClosure::do_cld(ClassLoaderData* cld) {
48   oop cl = cld->class_loader();
49   ClassLoaderStats* cls;
50 
51   // The hashtable key is the ClassLoader oop since we want to account
52   // for "real" classes and anonymous classes together
53   ClassLoaderStats** cls_ptr = _stats->get(cl);
54   if (cls_ptr == NULL) {
55     cls = new ClassLoaderStats();
56     _stats->put(cl, cls);
57     _total_loaders++;
58   } else {
59     cls = *cls_ptr;
60   }
61 
62   if (!cld->is_unsafe_anonymous()) {
63     cls->_cld = cld;
64   }
65 
66   cls->_class_loader = cl;
67   if (cl != NULL) {
68     cls->_parent = java_lang_ClassLoader::parent(cl);
69     addEmptyParents(cls->_parent);
70   }
71 
72   ClassStatsClosure csc;
73   cld->classes_do(&csc);
74   if(cld->is_unsafe_anonymous()) {
75     cls->_anon_classes_count += csc._num_classes;
76   } else {
77     cls->_classes_count = csc._num_classes;
78   }
79   _total_classes += csc._num_classes;
80 
81   ClassLoaderMetaspace* ms = cld->metaspace_or_null();
82   if (ms != NULL) {
83     if(cld->is_unsafe_anonymous()) {
84       cls->_anon_chunk_sz += ms->allocated_chunks_bytes();
85       cls->_anon_block_sz += ms->allocated_blocks_bytes();
86     } else {
87       cls->_chunk_sz = ms->allocated_chunks_bytes();
88       cls->_block_sz = ms->allocated_blocks_bytes();
89     }
90     _total_chunk_sz += ms->allocated_chunks_bytes();
91     _total_block_sz += ms->allocated_blocks_bytes();
92   }
93 }
94 
95 
96 // Handles the difference in pointer width on 32 and 64 bit platforms
97 #ifdef _LP64
98   #define SPACE "%8s"
99 #else
100   #define SPACE "%s"
101 #endif
102 
103 
do_entry(oop const & key,ClassLoaderStats * const & cls)104 bool ClassLoaderStatsClosure::do_entry(oop const& key, ClassLoaderStats* const& cls) {
105   Klass* class_loader_klass = (cls->_class_loader == NULL ? NULL : cls->_class_loader->klass());
106   Klass* parent_klass = (cls->_parent == NULL ? NULL : cls->_parent->klass());
107 
108   _out->print(INTPTR_FORMAT "  " INTPTR_FORMAT "  " INTPTR_FORMAT "  " UINTX_FORMAT_W(6) "  " SIZE_FORMAT_W(8) "  " SIZE_FORMAT_W(8) "  ",
109       p2i(class_loader_klass), p2i(parent_klass), p2i(cls->_cld),
110       cls->_classes_count,
111       cls->_chunk_sz, cls->_block_sz);
112   if (class_loader_klass != NULL) {
113     _out->print("%s", class_loader_klass->external_name());
114   } else {
115     _out->print("<boot class loader>");
116   }
117   _out->cr();
118   if (cls->_anon_classes_count > 0) {
119     _out->print_cr(SPACE SPACE SPACE "                                    " UINTX_FORMAT_W(6) "  " SIZE_FORMAT_W(8) "  " SIZE_FORMAT_W(8) "   + unsafe anonymous classes",
120         "", "", "",
121         cls->_anon_classes_count,
122         cls->_anon_chunk_sz, cls->_anon_block_sz);
123   }
124   return true;
125 }
126 
127 
print()128 void ClassLoaderStatsClosure::print() {
129   _out->print_cr("ClassLoader" SPACE " Parent" SPACE "      CLD*" SPACE "       Classes   ChunkSz   BlockSz  Type", "", "", "");
130   _stats->iterate(this);
131   _out->print("Total = " UINTX_FORMAT_W(-6), _total_loaders);
132   _out->print(SPACE SPACE SPACE "                      ", "", "", "");
133   _out->print_cr(UINTX_FORMAT_W(6) "  " SIZE_FORMAT_W(8) "  " SIZE_FORMAT_W(8) "  ",
134       _total_classes,
135       _total_chunk_sz,
136       _total_block_sz);
137   _out->print_cr("ChunkSz: Total size of all allocated metaspace chunks");
138   _out->print_cr("BlockSz: Total size of all allocated metaspace blocks (each chunk has several blocks)");
139 }
140 
141 
addEmptyParents(oop cl)142 void ClassLoaderStatsClosure::addEmptyParents(oop cl) {
143   while (cl != NULL && java_lang_ClassLoader::loader_data_acquire(cl) == NULL) {
144     // This classloader has not loaded any classes
145     ClassLoaderStats** cls_ptr = _stats->get(cl);
146     if (cls_ptr == NULL) {
147       // It does not exist in our table - add it
148       ClassLoaderStats* cls = new ClassLoaderStats();
149       cls->_class_loader = cl;
150       cls->_parent = java_lang_ClassLoader::parent(cl);
151       _stats->put(cl, cls);
152       _total_loaders++;
153     }
154 
155     cl = java_lang_ClassLoader::parent(cl);
156   }
157 }
158 
159 
doit()160 void ClassLoaderStatsVMOperation::doit() {
161   ClassLoaderStatsClosure clsc (_out);
162   ClassLoaderDataGraph::loaded_cld_do(&clsc);
163   clsc.print();
164 }
165 
166 
execute(DCmdSource source,TRAPS)167 void ClassLoaderStatsDCmd::execute(DCmdSource source, TRAPS) {
168   ClassLoaderStatsVMOperation op(output());
169   VMThread::execute(&op);
170 }
171