dbuck@9063: /* dbuck@9063: * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. dbuck@9063: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. dbuck@9063: * dbuck@9063: * This code is free software; you can redistribute it and/or modify it dbuck@9063: * under the terms of the GNU General Public License version 2 only, as dbuck@9063: * published by the Free Software Foundation. dbuck@9063: * dbuck@9063: * This code is distributed in the hope that it will be useful, but WITHOUT dbuck@9063: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or dbuck@9063: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License dbuck@9063: * version 2 for more details (a copy is included in the LICENSE file that dbuck@9063: * accompanied this code). dbuck@9063: * dbuck@9063: * You should have received a copy of the GNU General Public License version dbuck@9063: * 2 along with this work; if not, write to the Free Software Foundation, dbuck@9063: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. dbuck@9063: * dbuck@9063: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA dbuck@9063: * or visit www.oracle.com if you need additional information or have any dbuck@9063: * questions. dbuck@9063: * dbuck@9063: */ dbuck@9063: dbuck@9063: #include "precompiled.hpp" dbuck@9063: #include "classfile/classLoaderStats.hpp" dbuck@9063: #include "utilities/globalDefinitions.hpp" dbuck@9063: dbuck@9063: dbuck@9063: class ClassStatsClosure : public KlassClosure { dbuck@9063: public: dbuck@9063: int _num_classes; dbuck@9063: dbuck@9063: ClassStatsClosure() : dbuck@9063: _num_classes(0) { dbuck@9063: } dbuck@9063: dbuck@9063: virtual void do_klass(Klass* k) { dbuck@9063: _num_classes++; dbuck@9063: } dbuck@9063: }; dbuck@9063: dbuck@9063: dbuck@9063: void ClassLoaderStatsClosure::do_cld(ClassLoaderData* cld) { dbuck@9063: oop cl = cld->class_loader(); dbuck@9063: ClassLoaderStats* cls; dbuck@9063: dbuck@9063: // The hashtable key is the ClassLoader oop since we want to account dbuck@9063: // for "real" classes and anonymous classes together dbuck@9063: ClassLoaderStats** cls_ptr = _stats->get(cl); dbuck@9063: if (cls_ptr == NULL) { dbuck@9063: cls = new ClassLoaderStats(); dbuck@9063: _stats->put(cl, cls); dbuck@9063: _total_loaders++; dbuck@9063: } else { dbuck@9063: cls = *cls_ptr; dbuck@9063: } dbuck@9063: dbuck@9063: if (!cld->is_anonymous()) { dbuck@9063: cls->_cld = cld; dbuck@9063: } dbuck@9063: dbuck@9063: cls->_class_loader = cl; dbuck@9063: if (cl != NULL) { dbuck@9063: cls->_parent = java_lang_ClassLoader::parent(cl); dbuck@9063: addEmptyParents(cls->_parent); dbuck@9063: } dbuck@9063: dbuck@9063: ClassStatsClosure csc; dbuck@9063: cld->classes_do(&csc); dbuck@9063: if(cld->is_anonymous()) { dbuck@9063: cls->_anon_classes_count += csc._num_classes; dbuck@9063: } else { dbuck@9063: cls->_classes_count = csc._num_classes; dbuck@9063: } dbuck@9063: _total_classes += csc._num_classes; dbuck@9063: dbuck@9063: Metaspace* ms = cld->metaspace_or_null(); dbuck@9063: if (ms != NULL) { dbuck@9063: if(cld->is_anonymous()) { dbuck@9063: cls->_anon_chunk_sz += ms->allocated_chunks_bytes(); dbuck@9063: cls->_anon_block_sz += ms->allocated_blocks_bytes(); dbuck@9063: } else { dbuck@9063: cls->_chunk_sz = ms->allocated_chunks_bytes(); dbuck@9063: cls->_block_sz = ms->allocated_blocks_bytes(); dbuck@9063: } dbuck@9063: _total_chunk_sz += ms->allocated_chunks_bytes(); dbuck@9063: _total_block_sz += ms->allocated_blocks_bytes(); dbuck@9063: } dbuck@9063: } dbuck@9063: dbuck@9063: dbuck@9063: // Handles the difference in pointer width on 32 and 64 bit platforms dbuck@9063: #ifdef _LP64 dbuck@9063: #define SPACE "%8s" dbuck@9063: #else dbuck@9063: #define SPACE "%s" dbuck@9063: #endif dbuck@9063: dbuck@9063: dbuck@9063: bool ClassLoaderStatsClosure::do_entry(oop const& key, ClassLoaderStats* const& cls) { dbuck@9063: Klass* class_loader_klass = (cls->_class_loader == NULL ? NULL : cls->_class_loader->klass()); dbuck@9063: Klass* parent_klass = (cls->_parent == NULL ? NULL : cls->_parent->klass()); dbuck@9063: dbuck@9063: _out->print(INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " UINTX_FORMAT_W(6) " " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(8) " ", dbuck@9063: p2i(class_loader_klass), p2i(parent_klass), p2i(cls->_cld), dbuck@9063: cls->_classes_count, dbuck@9063: cls->_chunk_sz, cls->_block_sz); dbuck@9063: if (class_loader_klass != NULL) { dbuck@9063: _out->print("%s", class_loader_klass->external_name()); dbuck@9063: } else { dbuck@9063: _out->print(""); dbuck@9063: } dbuck@9063: _out->cr(); dbuck@9063: if (cls->_anon_classes_count > 0) { dbuck@9063: _out->print_cr(SPACE SPACE SPACE " " UINTX_FORMAT_W(6) " " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(8) " + unsafe anonymous classes", dbuck@9063: "", "", "", dbuck@9063: cls->_anon_classes_count, dbuck@9063: cls->_anon_chunk_sz, cls->_anon_block_sz); dbuck@9063: } dbuck@9063: return true; dbuck@9063: } dbuck@9063: dbuck@9063: dbuck@9063: void ClassLoaderStatsClosure::print() { dbuck@9063: _out->print_cr("ClassLoader" SPACE " Parent" SPACE " CLD*" SPACE " Classes ChunkSz BlockSz Type", "", "", ""); dbuck@9063: _stats->iterate(this); dbuck@9063: _out->print("Total = " UINTX_FORMAT_W(-6), _total_loaders); dbuck@9063: _out->print(SPACE SPACE SPACE " ", "", "", ""); dbuck@9063: _out->print_cr(UINTX_FORMAT_W(6) " " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(8) " ", dbuck@9063: _total_classes, dbuck@9063: _total_chunk_sz, dbuck@9063: _total_block_sz); dbuck@9063: _out->print_cr("ChunkSz: Total size of all allocated metaspace chunks"); dbuck@9063: _out->print_cr("BlockSz: Total size of all allocated metaspace blocks (each chunk has several blocks)"); dbuck@9063: } dbuck@9063: dbuck@9063: dbuck@9063: void ClassLoaderStatsClosure::addEmptyParents(oop cl) { dbuck@9063: while (cl != NULL && java_lang_ClassLoader::loader_data(cl) == NULL) { dbuck@9063: // This classloader has not loaded any classes dbuck@9063: ClassLoaderStats** cls_ptr = _stats->get(cl); dbuck@9063: if (cls_ptr == NULL) { dbuck@9063: // It does not exist in our table - add it dbuck@9063: ClassLoaderStats* cls = new ClassLoaderStats(); dbuck@9063: cls->_class_loader = cl; dbuck@9063: cls->_parent = java_lang_ClassLoader::parent(cl); dbuck@9063: _stats->put(cl, cls); dbuck@9063: _total_loaders++; dbuck@9063: } dbuck@9063: dbuck@9063: cl = java_lang_ClassLoader::parent(cl); dbuck@9063: } dbuck@9063: } dbuck@9063: dbuck@9063: dbuck@9063: void ClassLoaderStatsVMOperation::doit() { dbuck@9063: ClassLoaderStatsClosure clsc (_out); dbuck@9063: ClassLoaderDataGraph::cld_do(&clsc); dbuck@9063: clsc.print(); dbuck@9063: } dbuck@9063: dbuck@9063: dbuck@9063: void ClassLoaderStatsDCmd::execute(DCmdSource source, TRAPS) { dbuck@9063: ClassLoaderStatsVMOperation op(output()); dbuck@9063: VMThread::execute(&op); dbuck@9063: }