Path: blob/master/src/hotspot/share/memory/heapInspection.hpp
40949 views
/*1* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_MEMORY_HEAPINSPECTION_HPP25#define SHARE_MEMORY_HEAPINSPECTION_HPP2627#include "memory/allocation.hpp"28#include "oops/objArrayOop.hpp"29#include "oops/oop.hpp"30#include "oops/annotations.hpp"31#include "utilities/macros.hpp"32#include "gc/shared/workgroup.hpp"3334class ParallelObjectIterator;3536#if INCLUDE_SERVICES373839// HeapInspection4041// KlassInfoTable is a bucket hash table that42// maps Klass*s to extra information:43// instance count and instance word size.44//45// A KlassInfoBucket is the head of a link list46// of KlassInfoEntry's47//48// KlassInfoHisto is a growable array of pointers49// to KlassInfoEntry's and is used to sort50// the entries.5152class KlassInfoEntry: public CHeapObj<mtInternal> {53private:54KlassInfoEntry* _next;55Klass* _klass;56uint64_t _instance_count;57size_t _instance_words;58int64_t _index;59bool _do_print; // True if we should print this class when printing the class hierarchy.60GrowableArray<KlassInfoEntry*>* _subclasses;6162public:63KlassInfoEntry(Klass* k, KlassInfoEntry* next) :64_next(next), _klass(k), _instance_count(0), _instance_words(0), _index(-1),65_do_print(false), _subclasses(NULL)66{}67~KlassInfoEntry();68KlassInfoEntry* next() const { return _next; }69bool is_equal(const Klass* k) { return k == _klass; }70Klass* klass() const { return _klass; }71uint64_t count() const { return _instance_count; }72void set_count(uint64_t ct) { _instance_count = ct; }73size_t words() const { return _instance_words; }74void set_words(size_t wds) { _instance_words = wds; }75void set_index(int64_t index) { _index = index; }76int64_t index() const { return _index; }77GrowableArray<KlassInfoEntry*>* subclasses() const { return _subclasses; }78void add_subclass(KlassInfoEntry* cie);79void set_do_print(bool do_print) { _do_print = do_print; }80bool do_print() const { return _do_print; }81int compare(KlassInfoEntry* e1, KlassInfoEntry* e2);82void print_on(outputStream* st) const;83const char* name() const;84};8586class KlassInfoClosure : public StackObj {87public:88// Called for each KlassInfoEntry.89virtual void do_cinfo(KlassInfoEntry* cie) = 0;90};9192class KlassInfoBucket: public CHeapObj<mtInternal> {93private:94KlassInfoEntry* _list;95KlassInfoEntry* list() { return _list; }96void set_list(KlassInfoEntry* l) { _list = l; }97public:98KlassInfoEntry* lookup(Klass* k);99void initialize() { _list = NULL; }100void empty();101void iterate(KlassInfoClosure* cic);102};103104class KlassInfoTable: public StackObj {105private:106static const int _num_buckets = 20011;107size_t _size_of_instances_in_words;108109// An aligned reference address (typically the least110// address in the perm gen) used for hashing klass111// objects.112HeapWord* _ref;113114KlassInfoBucket* _buckets;115uint hash(const Klass* p);116KlassInfoEntry* lookup(Klass* k); // allocates if not found!117118class AllClassesFinder;119120public:121KlassInfoTable(bool add_all_classes);122~KlassInfoTable();123bool record_instance(const oop obj);124void iterate(KlassInfoClosure* cic);125bool allocation_failed() { return _buckets == NULL; }126size_t size_of_instances_in_words() const;127bool merge(KlassInfoTable* table);128bool merge_entry(const KlassInfoEntry* cie);129130friend class KlassInfoHisto;131friend class KlassHierarchy;132};133134class KlassHierarchy : AllStatic {135public:136static void print_class_hierarchy(outputStream* st, bool print_interfaces, bool print_subclasses,137char* classname);138139private:140static void set_do_print_for_class_hierarchy(KlassInfoEntry* cie, KlassInfoTable* cit,141bool print_subclasse);142static void print_class(outputStream* st, KlassInfoEntry* cie, bool print_subclasses);143};144145class KlassInfoHisto : public StackObj {146private:147static const int _histo_initial_size = 1000;148KlassInfoTable *_cit;149GrowableArray<KlassInfoEntry*>* _elements;150GrowableArray<KlassInfoEntry*>* elements() const { return _elements; }151static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2);152void print_elements(outputStream* st) const;153bool is_selected(const char *col_name);154155template <class T> static int count_bytes(T* x) {156return (HeapWordSize * ((x) ? (x)->size() : 0));157}158159template <class T> static int count_bytes_array(T* x) {160if (x == NULL) {161return 0;162}163if (x->length() == 0) {164// This is a shared array, e.g., Universe::the_empty_int_array(). Don't165// count it to avoid double-counting.166return 0;167}168return HeapWordSize * x->size();169}170171static void print_julong(outputStream* st, int width, julong n) {172int num_spaces = width - julong_width(n);173if (num_spaces > 0) {174st->print("%*s", num_spaces, "");175}176st->print(JULONG_FORMAT, n);177}178179static int julong_width(julong n) {180if (n == 0) {181return 1;182}183int w = 0;184while (n > 0) {185n /= 10;186w += 1;187}188return w;189}190191static int col_width(julong n, const char *name) {192int w = julong_width(n);193int min = (int)(strlen(name));194if (w < min) {195w = min;196}197// add a leading space for separation.198return w + 1;199}200201public:202KlassInfoHisto(KlassInfoTable* cit);203~KlassInfoHisto();204void add(KlassInfoEntry* cie);205void print_histo_on(outputStream* st);206void sort();207};208209#endif // INCLUDE_SERVICES210211// These declarations are needed since the declaration of KlassInfoTable and212// KlassInfoClosure are guarded by #if INLCUDE_SERVICES213class KlassInfoTable;214class KlassInfoClosure;215216class HeapInspection : public StackObj {217public:218void heap_inspection(outputStream* st, uint parallel_thread_num = 1) NOT_SERVICES_RETURN;219uintx populate_table(KlassInfoTable* cit, BoolObjectClosure* filter = NULL, uint parallel_thread_num = 1) NOT_SERVICES_RETURN_(0);220static void find_instances_at_safepoint(Klass* k, GrowableArray<oop>* result) NOT_SERVICES_RETURN;221private:222void iterate_over_heap(KlassInfoTable* cit, BoolObjectClosure* filter = NULL);223};224225// Parallel heap inspection task. Parallel inspection can fail due to226// a native OOM when allocating memory for TL-KlassInfoTable.227// _success will be set false on an OOM, and serial inspection tried.228class ParHeapInspectTask : public AbstractGangTask {229private:230ParallelObjectIterator* _poi;231KlassInfoTable* _shared_cit;232BoolObjectClosure* _filter;233uintx _missed_count;234bool _success;235Mutex _mutex;236237public:238ParHeapInspectTask(ParallelObjectIterator* poi,239KlassInfoTable* shared_cit,240BoolObjectClosure* filter) :241AbstractGangTask("Iterating heap"),242_poi(poi),243_shared_cit(shared_cit),244_filter(filter),245_missed_count(0),246_success(true),247_mutex(Mutex::leaf, "Parallel heap iteration data merge lock") {}248249uintx missed_count() const {250return _missed_count;251}252253bool success() {254return _success;255}256257virtual void work(uint worker_id);258};259260#endif // SHARE_MEMORY_HEAPINSPECTION_HPP261262263