--- old/src/hotspot/share/memory/metaspace.cpp 2018-05-19 07:08:27.157647136 +0200 +++ new/src/hotspot/share/memory/metaspace.cpp 2018-05-19 07:08:26.965645647 +0200 @@ -602,11 +602,12 @@ void MetaspaceUtils::print_report(outputStream* out, size_t scale, int flags) { const bool print_loaders = (flags & rf_show_loaders) > 0; + const bool print_classes = (flags & rf_show_classes) > 0; const bool print_by_chunktype = (flags & rf_break_down_by_chunktype) > 0; const bool print_by_spacetype = (flags & rf_break_down_by_spacetype) > 0; // Some report options require walking the class loader data graph. - PrintCLDMetaspaceInfoClosure cl(out, scale, print_loaders, print_by_chunktype); + PrintCLDMetaspaceInfoClosure cl(out, scale, print_loaders, print_classes, print_by_chunktype); if (print_loaders) { out->cr(); out->print_cr("Usage per loader:"); --- old/src/hotspot/share/memory/metaspace.hpp 2018-05-19 07:08:28.089654362 +0200 +++ new/src/hotspot/share/memory/metaspace.hpp 2018-05-19 07:08:27.929653121 +0200 @@ -389,7 +389,9 @@ // Print details about the underlying virtual spaces. rf_show_vslist = (1 << 3), // Print metaspace map. - rf_show_vsmap = (1 << 4) + rf_show_vsmap = (1 << 4), + // If show_loaders: show loaded classes for each loader. + rf_show_classes = (1 << 5) }; // This will print out a basic metaspace usage report but --- old/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp 2018-05-19 07:08:28.821660037 +0200 +++ new/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp 2018-05-19 07:08:28.661658797 +0200 @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP and/or its affiliates. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +35,7 @@ : DCmdWithParser(output, heap) , _basic("basic", "Prints a basic summary (does not need a safepoint).", "BOOLEAN", false, "false") , _show_loaders("show-loaders", "Shows usage by class loader.", "BOOLEAN", false, "false") + , _show_classes("show-classes", "If show-loaders is set, shows loaded classes for each loader.", "BOOLEAN", false, "false") , _by_chunktype("by-chunktype", "Break down numbers by chunk type.", "BOOLEAN", false, "false") , _by_spacetype("by-spacetype", "Break down numbers by loader type.", "BOOLEAN", false, "false") , _show_vslist("vslist", "Shows details about the underlying virtual space.", "BOOLEAN", false, "false") @@ -44,6 +46,7 @@ { _dcmdparser.add_dcmd_option(&_basic); _dcmdparser.add_dcmd_option(&_show_loaders); + _dcmdparser.add_dcmd_option(&_show_classes); _dcmdparser.add_dcmd_option(&_by_chunktype); _dcmdparser.add_dcmd_option(&_by_spacetype); _dcmdparser.add_dcmd_option(&_show_vslist); @@ -87,6 +90,7 @@ // Full mode. Requires safepoint. int flags = 0; if (_show_loaders.value()) flags |= MetaspaceUtils::rf_show_loaders; + if (_show_classes.value()) flags |= MetaspaceUtils::rf_show_classes; if (_by_chunktype.value()) flags |= MetaspaceUtils::rf_break_down_by_chunktype; if (_by_spacetype.value()) flags |= MetaspaceUtils::rf_break_down_by_spacetype; if (_show_vslist.value()) flags |= MetaspaceUtils::rf_show_vslist; --- old/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp 2018-05-19 07:08:29.529665526 +0200 +++ new/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp 2018-05-19 07:08:29.369664286 +0200 @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP and/or its affiliates. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +40,7 @@ DCmdArgument _show_vslist; DCmdArgument _show_vsmap; DCmdArgument _scale; + DCmdArgument _show_classes; public: MetaspaceDCmd(outputStream* output, bool heap); static const char* name() { --- old/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp 2018-05-19 07:08:30.321671666 +0200 +++ new/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp 2018-05-19 07:08:30.177670550 +0200 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.hpp" #include "memory/metaspace/printCLDMetaspaceInfoClosure.hpp" +#include "memory/metaspace/printMetaspaceInfoKlassClosure.hpp" #include "memory/resourceArea.hpp" #include "runtime/safepoint.hpp" #include "utilities/globalDefinitions.hpp" @@ -32,19 +33,31 @@ namespace metaspace { -PrintCLDMetaspaceInfoClosure::PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale, bool do_print, bool break_down_by_chunktype) -: _out(out), _scale(scale), _do_print(do_print), _break_down_by_chunktype(break_down_by_chunktype) -, _num_loaders(0) +PrintCLDMetaspaceInfoClosure::PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale, bool do_print, + bool do_print_classes, bool break_down_by_chunktype) +: _out(out), _scale(scale), _do_print(do_print), _do_print_classes(do_print_classes) +, _break_down_by_chunktype(break_down_by_chunktype) +, _num_loaders(0), _num_loaders_unloading(0), _num_loaders_without_metaspace(0) { memset(_num_loaders_by_spacetype, 0, sizeof(_num_loaders_by_spacetype)); } +static const char* classes_plural(uintx num) { + return num == 1 ? "" : "es"; +} + void PrintCLDMetaspaceInfoClosure::do_cld(ClassLoaderData* cld) { assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); + if (cld->is_unloading()) { + _num_loaders_unloading ++; + return; + } + ClassLoaderMetaspace* msp = cld->metaspace_or_null(); if (msp == NULL) { + _num_loaders_without_metaspace ++; return; } @@ -70,10 +83,33 @@ _out->print("ClassLoaderData " PTR_FORMAT " for %s", p2i(cld), cld->loader_name()); } - if (cld->is_unloading()) { - _out->print(" (unloading)"); + if (_do_print_classes) { + streamIndentor sti(_out, 6); + _out->cr_indent(); + _out->print("Loaded classes: "); + PrintMetaspaceInfoKlassClosure pkic(_out, true); + cld->classes_do(&pkic); + _out->cr_indent(); + _out->print("-total-: "); + _out->print(UINTX_FORMAT " class%s", pkic._num_classes, classes_plural(pkic._num_classes)); + if (pkic._num_instance_classes > 0 || pkic._num_array_classes > 0) { + _out->print(" ("); + if (pkic._num_instance_classes > 0) { + _out->print(UINTX_FORMAT " instance class%s", pkic._num_instance_classes, + classes_plural(pkic._num_instance_classes)); + } + if (pkic._num_array_classes > 0) { + if (pkic._num_instance_classes > 0) { + _out->print(", "); + } + _out->print(UINTX_FORMAT " array class%s", pkic._num_array_classes, + classes_plural(pkic._num_array_classes)); + } + _out->print(")."); + } } + _out->cr(); this_cld_stat.print_on(_out, _scale, _break_down_by_chunktype); _out->cr(); --- old/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.hpp 2018-05-19 07:08:31.209678551 +0200 +++ new/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.hpp 2018-05-19 07:08:31.069677466 +0200 @@ -39,17 +39,21 @@ outputStream* const _out; const size_t _scale; const bool _do_print; + const bool _do_print_classes; const bool _break_down_by_chunktype; public: uintx _num_loaders; + uintx _num_loaders_without_metaspace; + uintx _num_loaders_unloading; ClassLoaderMetaspaceStatistics _stats_total; uintx _num_loaders_by_spacetype [Metaspace::MetaspaceTypeCount]; ClassLoaderMetaspaceStatistics _stats_by_spacetype [Metaspace::MetaspaceTypeCount]; - PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale, bool do_print, bool break_down_by_chunktype); + PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale, bool do_print, + bool do_print_classes, bool break_down_by_chunktype); void do_cld(ClassLoaderData* cld); }; --- /dev/null 2018-05-19 05:41:07.974266360 +0200 +++ new/src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.cpp 2018-05-19 07:08:31.909683978 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP and/or its affiliates. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#include "precompiled.hpp" + +#include "classfile/systemDictionary.hpp" +#include "memory/metaspace/printMetaspaceInfoKlassClosure.hpp" +#include "memory/resourceArea.hpp" +#include "oops/constantPool.inline.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/klass.hpp" +#include "utilities/constantTag.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + + +namespace metaspace { + +PrintMetaspaceInfoKlassClosure::PrintMetaspaceInfoKlassClosure(outputStream* out, bool do_print) +: _out(out), _do_print(do_print) +, _num_classes(0), _num_instance_classes(0), _num_array_classes(0) { +} + +void PrintMetaspaceInfoKlassClosure::do_klass(Klass* k) { + _num_classes ++; + if (k->is_instance_klass()) { + _num_instance_classes ++; + } else if (k->is_array_klass()) { + _num_array_classes ++; + } + if (_do_print) { + _out->cr_indent(); + _out->print(UINTX_FORMAT_W(4) ": ", _num_classes); + ResourceMark rm; + _out->print("%s", k->external_name()); + } +} + +} // namespace metaspace --- /dev/null 2018-05-19 05:41:07.974266360 +0200 +++ new/src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.hpp 2018-05-19 07:08:32.757690550 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP and/or its affiliates. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_MEMORY_METASPACE_PRINTMETASPACEINFOKLASSCLOSURE_HPP_ +#define SHARE_MEMORY_METASPACE_PRINTMETASPACEINFOKLASSCLOSURE_HPP_ + +#include "memory/iterator.hpp" +#include "utilities/globalDefinitions.hpp" + +class outputStream; +class InstanceKlass; + +namespace metaspace { + +// Helper class for MetaspaceUtils::print_report() +class PrintMetaspaceInfoKlassClosure : public KlassClosure { +private: + outputStream* const _out; + const bool _do_print; + +public: + uintx _num_classes; + uintx _num_instance_classes; + uintx _num_array_classes; + + PrintMetaspaceInfoKlassClosure(outputStream* out, bool do_print); + void do_klass(Klass* k); + +}; // end: PrintKlassInfoClosure + +} // namespace metaspace + +#endif /* SHARE_MEMORY_METASPACE_PRINTMETASPACEINFOKLASSCLOSURE_HPP_ */