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 #include "gc/shared/workgroup.hpp"
34 
35 class ParallelObjectIterator;
36 
37 #if INCLUDE_SERVICES
38 
39 
40 // HeapInspection
41 
42 // KlassInfoTable is a bucket hash table that
43 // maps Klass*s to extra information:
44 //    instance count and instance word size.
45 //
46 // A KlassInfoBucket is the head of a link list
47 // of KlassInfoEntry's
48 //
49 // KlassInfoHisto is a growable array of pointers
50 // to KlassInfoEntry's and is used to sort
51 // the entries.
52 
53 class KlassInfoEntry: public CHeapObj<mtInternal> {
54  private:
55   KlassInfoEntry* _next;
56   Klass*          _klass;
57   uint64_t        _instance_count;
58   size_t          _instance_words;
59   int64_t         _index;
60   bool            _do_print; // True if we should print this class when printing the class hierarchy.
61   GrowableArray<KlassInfoEntry*>* _subclasses;
62 
63  public:
KlassInfoEntry(Klass * k,KlassInfoEntry * next)64   KlassInfoEntry(Klass* k, KlassInfoEntry* next) :
65     _next(next), _klass(k), _instance_count(0), _instance_words(0), _index(-1),
66     _do_print(false), _subclasses(NULL)
67   {}
68   ~KlassInfoEntry();
next() const69   KlassInfoEntry* next() const   { return _next; }
is_equal(const Klass * k)70   bool is_equal(const Klass* k)  { return k == _klass; }
klass() const71   Klass* klass()  const          { return _klass; }
count() const72   uint64_t count()    const      { return _instance_count; }
set_count(uint64_t ct)73   void set_count(uint64_t ct)    { _instance_count = ct; }
words() const74   size_t words()  const          { return _instance_words; }
set_words(size_t wds)75   void set_words(size_t wds)     { _instance_words = wds; }
set_index(int64_t index)76   void set_index(int64_t index)  { _index = index; }
index() const77   int64_t index()    const       { return _index; }
subclasses() const78   GrowableArray<KlassInfoEntry*>* subclasses() const { return _subclasses; }
79   void add_subclass(KlassInfoEntry* cie);
set_do_print(bool do_print)80   void set_do_print(bool do_print) { _do_print = do_print; }
do_print() const81   bool do_print() const      { return _do_print; }
82   int compare(KlassInfoEntry* e1, KlassInfoEntry* e2);
83   void print_on(outputStream* st) const;
84   const char* name() const;
85 };
86 
87 class KlassInfoClosure : public StackObj {
88  public:
89   // Called for each KlassInfoEntry.
90   virtual void do_cinfo(KlassInfoEntry* cie) = 0;
91 };
92 
93 class KlassInfoBucket: public CHeapObj<mtInternal> {
94  private:
95   KlassInfoEntry* _list;
list()96   KlassInfoEntry* list()           { return _list; }
set_list(KlassInfoEntry * l)97   void set_list(KlassInfoEntry* l) { _list = l; }
98  public:
99   KlassInfoEntry* lookup(Klass* k);
initialize()100   void initialize() { _list = NULL; }
101   void empty();
102   void iterate(KlassInfoClosure* cic);
103 };
104 
105 class KlassInfoTable: public StackObj {
106  private:
107   static const int _num_buckets = 20011;
108   size_t _size_of_instances_in_words;
109 
110   // An aligned reference address (typically the least
111   // address in the perm gen) used for hashing klass
112   // objects.
113   HeapWord* _ref;
114 
115   KlassInfoBucket* _buckets;
116   uint hash(const Klass* p);
117   KlassInfoEntry* lookup(Klass* k); // allocates if not found!
118 
119   class AllClassesFinder;
120 
121  public:
122   KlassInfoTable(bool add_all_classes);
123   ~KlassInfoTable();
124   bool record_instance(const oop obj);
125   void iterate(KlassInfoClosure* cic);
allocation_failed()126   bool allocation_failed() { return _buckets == NULL; }
127   size_t size_of_instances_in_words() const;
128   bool merge(KlassInfoTable* table);
129   bool merge_entry(const KlassInfoEntry* cie);
130 
131   friend class KlassInfoHisto;
132   friend class KlassHierarchy;
133 };
134 
135 class KlassHierarchy : AllStatic {
136  public:
137   static void print_class_hierarchy(outputStream* st, bool print_interfaces,  bool print_subclasses,
138                                     char* classname);
139 
140  private:
141   static void set_do_print_for_class_hierarchy(KlassInfoEntry* cie, KlassInfoTable* cit,
142                                                bool print_subclasse);
143   static void print_class(outputStream* st, KlassInfoEntry* cie, bool print_subclasses);
144 };
145 
146 class KlassInfoHisto : public StackObj {
147  private:
148   static const int _histo_initial_size = 1000;
149   KlassInfoTable *_cit;
150   GrowableArray<KlassInfoEntry*>* _elements;
elements() const151   GrowableArray<KlassInfoEntry*>* elements() const { return _elements; }
152   static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2);
153   void print_elements(outputStream* st) const;
154   bool is_selected(const char *col_name);
155 
count_bytes(T * x)156   template <class T> static int count_bytes(T* x) {
157     return (HeapWordSize * ((x) ? (x)->size() : 0));
158   }
159 
count_bytes_array(T * x)160   template <class T> static int count_bytes_array(T* x) {
161     if (x == NULL) {
162       return 0;
163     }
164     if (x->length() == 0) {
165       // This is a shared array, e.g., Universe::the_empty_int_array(). Don't
166       // count it to avoid double-counting.
167       return 0;
168     }
169     return HeapWordSize * x->size();
170   }
171 
print_julong(outputStream * st,int width,julong n)172   static void print_julong(outputStream* st, int width, julong n) {
173     int num_spaces = width - julong_width(n);
174     if (num_spaces > 0) {
175       st->print("%*s", num_spaces, "");
176     }
177     st->print(JULONG_FORMAT, n);
178   }
179 
julong_width(julong n)180   static int julong_width(julong n) {
181     if (n == 0) {
182       return 1;
183     }
184     int w = 0;
185     while (n > 0) {
186       n /= 10;
187       w += 1;
188     }
189     return w;
190   }
191 
col_width(julong n,const char * name)192   static int col_width(julong n, const char *name) {
193     int w = julong_width(n);
194     int min = (int)(strlen(name));
195     if (w < min) {
196         w = min;
197     }
198     // add a leading space for separation.
199     return w + 1;
200   }
201 
202  public:
203   KlassInfoHisto(KlassInfoTable* cit);
204   ~KlassInfoHisto();
205   void add(KlassInfoEntry* cie);
206   void print_histo_on(outputStream* st);
207   void sort();
208 };
209 
210 #endif // INCLUDE_SERVICES
211 
212 // These declarations are needed since the declaration of KlassInfoTable and
213 // KlassInfoClosure are guarded by #if INLCUDE_SERVICES
214 class KlassInfoTable;
215 class KlassInfoClosure;
216 
217 class HeapInspection : public StackObj {
218  public:
219   void heap_inspection(outputStream* st, uint parallel_thread_num = 1) NOT_SERVICES_RETURN;
220   uintx populate_table(KlassInfoTable* cit, BoolObjectClosure* filter = NULL, uint parallel_thread_num = 1) NOT_SERVICES_RETURN_(0);
221   static void find_instances_at_safepoint(Klass* k, GrowableArray<oop>* result) NOT_SERVICES_RETURN;
222  private:
223   void iterate_over_heap(KlassInfoTable* cit, BoolObjectClosure* filter = NULL);
224 };
225 
226 // Parallel heap inspection task. Parallel inspection can fail due to
227 // a native OOM when allocating memory for TL-KlassInfoTable.
228 // _success will be set false on an OOM, and serial inspection tried.
229 class ParHeapInspectTask : public AbstractGangTask {
230  private:
231   ParallelObjectIterator* _poi;
232   KlassInfoTable* _shared_cit;
233   BoolObjectClosure* _filter;
234   uintx _missed_count;
235   bool _success;
236   Mutex _mutex;
237 
238  public:
ParHeapInspectTask(ParallelObjectIterator * poi,KlassInfoTable * shared_cit,BoolObjectClosure * filter)239   ParHeapInspectTask(ParallelObjectIterator* poi,
240                      KlassInfoTable* shared_cit,
241                      BoolObjectClosure* filter) :
242       AbstractGangTask("Iterating heap"),
243       _poi(poi),
244       _shared_cit(shared_cit),
245       _filter(filter),
246       _missed_count(0),
247       _success(true),
248       _mutex(Mutex::leaf, "Parallel heap iteration data merge lock") {}
249 
missed_count() const250   uintx missed_count() const {
251     return _missed_count;
252   }
253 
success()254   bool success() {
255     return _success;
256   }
257 
258   virtual void work(uint worker_id);
259 };
260 
261 #endif // SHARE_MEMORY_HEAPINSPECTION_HPP
262