1 /* 2 * Copyright (c) 2002, 2020, 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 #ifndef SHARE_MEMORY_HEAPINSPECTION_HPP 26 #define SHARE_MEMORY_HEAPINSPECTION_HPP 27 28 #include "memory/allocation.hpp" 29 #include "oops/objArrayOop.hpp" 30 #include "oops/oop.hpp" 31 #include "oops/annotations.hpp" 32 #include "utilities/macros.hpp" 33 34 #if INCLUDE_SERVICES 35 36 37 // HeapInspection 38 39 // KlassInfoTable is a bucket hash table that 40 // maps Klass*s to extra information: 41 // instance count and instance word size. 42 // 43 // A KlassInfoBucket is the head of a link list 44 // of KlassInfoEntry's 45 // 46 // KlassInfoHisto is a growable array of pointers 47 // to KlassInfoEntry's and is used to sort 48 // the entries. 49 50 class KlassInfoEntry: public CHeapObj<mtInternal> { 51 private: 52 KlassInfoEntry* _next; 53 Klass* _klass; 54 long _instance_count; 55 size_t _instance_words; 56 long _index; 57 bool _do_print; // True if we should print this class when printing the class hierarchy. 58 GrowableArray<KlassInfoEntry*>* _subclasses; 59 60 public: 61 KlassInfoEntry(Klass* k, KlassInfoEntry* next) : 62 _next(next), _klass(k), _instance_count(0), _instance_words(0), _index(-1), 63 _do_print(false), _subclasses(NULL) 64 {} 65 ~KlassInfoEntry(); 66 KlassInfoEntry* next() const { return _next; } 67 bool is_equal(const Klass* k) { return k == _klass; } 68 Klass* klass() const { return _klass; } 69 long count() const { return _instance_count; } 70 void set_count(long ct) { _instance_count = ct; } 71 size_t words() const { return _instance_words; } 72 void set_words(size_t wds) { _instance_words = wds; } 73 void set_index(long index) { _index = index; } 74 long index() const { return _index; } 75 GrowableArray<KlassInfoEntry*>* subclasses() const { return _subclasses; } 76 void add_subclass(KlassInfoEntry* cie); 77 void set_do_print(bool do_print) { _do_print = do_print; } 78 bool do_print() const { return _do_print; } 79 int compare(KlassInfoEntry* e1, KlassInfoEntry* e2); 80 void print_on(outputStream* st) const; 81 const char* name() const; 82 }; 83 84 class KlassInfoClosure : public StackObj { 85 public: 86 // Called for each KlassInfoEntry. 87 virtual void do_cinfo(KlassInfoEntry* cie) = 0; 88 }; 89 90 class KlassInfoBucket: public CHeapObj<mtInternal> { 91 private: 92 KlassInfoEntry* _list; 93 KlassInfoEntry* list() { return _list; } 94 void set_list(KlassInfoEntry* l) { _list = l; } 95 public: 96 KlassInfoEntry* lookup(Klass* k); 97 void initialize() { _list = NULL; } 98 void empty(); 99 void iterate(KlassInfoClosure* cic); 100 }; 101 102 class KlassInfoTable: public StackObj { 103 private: 104 static const int _num_buckets = 20011; 105 size_t _size_of_instances_in_words; 106 107 // An aligned reference address (typically the least 108 // address in the perm gen) used for hashing klass 109 // objects. 110 HeapWord* _ref; 111 112 KlassInfoBucket* _buckets; 113 uint hash(const Klass* p); 114 KlassInfoEntry* lookup(Klass* k); // allocates if not found! 115 116 class AllClassesFinder; 117 118 public: 119 KlassInfoTable(bool add_all_classes); 120 ~KlassInfoTable(); 121 bool record_instance(const oop obj); 122 void iterate(KlassInfoClosure* cic); 123 bool allocation_failed() { return _buckets == NULL; } 124 size_t size_of_instances_in_words() const; 125 126 friend class KlassInfoHisto; 127 friend class KlassHierarchy; 128 }; 129 130 class KlassHierarchy : AllStatic { 131 public: 132 static void print_class_hierarchy(outputStream* st, bool print_interfaces, bool print_subclasses, 133 char* classname); 134 135 private: 136 static void set_do_print_for_class_hierarchy(KlassInfoEntry* cie, KlassInfoTable* cit, 137 bool print_subclasse); 138 static void print_class(outputStream* st, KlassInfoEntry* cie, bool print_subclasses); 139 }; 140 141 class KlassInfoHisto : public StackObj { 142 private: 143 static const int _histo_initial_size = 1000; 144 KlassInfoTable *_cit; 145 GrowableArray<KlassInfoEntry*>* _elements; 146 GrowableArray<KlassInfoEntry*>* elements() const { return _elements; } 147 static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2); 148 void print_elements(outputStream* st) const; 149 bool is_selected(const char *col_name); 150 151 template <class T> static int count_bytes(T* x) { 152 return (HeapWordSize * ((x) ? (x)->size() : 0)); 153 } 154 155 template <class T> static int count_bytes_array(T* x) { 156 if (x == NULL) { 157 return 0; 158 } 159 if (x->length() == 0) { 160 // This is a shared array, e.g., Universe::the_empty_int_array(). Don't 161 // count it to avoid double-counting. 162 return 0; 163 } 164 return HeapWordSize * x->size(); 165 } 166 167 static void print_julong(outputStream* st, int width, julong n) { 168 int num_spaces = width - julong_width(n); 169 if (num_spaces > 0) { 170 st->print("%*s", num_spaces, ""); 171 } 172 st->print(JULONG_FORMAT, n); 173 } 174 175 static int julong_width(julong n) { 176 if (n == 0) { 177 return 1; 178 } 179 int w = 0; 180 while (n > 0) { 181 n /= 10; 182 w += 1; 183 } 184 return w; 185 } 186 187 static int col_width(julong n, const char *name) { 188 int w = julong_width(n); 189 int min = (int)(strlen(name)); 190 if (w < min) { 191 w = min; 192 } 193 // add a leading space for separation. 194 return w + 1; 195 } 196 197 public: 198 KlassInfoHisto(KlassInfoTable* cit); 199 ~KlassInfoHisto(); 200 void add(KlassInfoEntry* cie); 201 void print_histo_on(outputStream* st); 202 void sort(); 203 }; 204 205 #endif // INCLUDE_SERVICES 206 207 // These declarations are needed since the declaration of KlassInfoTable and 208 // KlassInfoClosure are guarded by #if INLCUDE_SERVICES 209 class KlassInfoTable; 210 class KlassInfoClosure; 211 212 class HeapInspection : public StackObj { 213 public: 214 void heap_inspection(outputStream* st) NOT_SERVICES_RETURN; 215 size_t populate_table(KlassInfoTable* cit, BoolObjectClosure* filter = NULL) NOT_SERVICES_RETURN_(0); 216 static void find_instances_at_safepoint(Klass* k, GrowableArray<oop>* result) NOT_SERVICES_RETURN; 217 private: 218 void iterate_over_heap(KlassInfoTable* cit, BoolObjectClosure* filter = NULL); 219 }; 220 221 #endif // SHARE_MEMORY_HEAPINSPECTION_HPP