Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/memory/heapInspection.hpp
40949 views
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:
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();
69
KlassInfoEntry* next() const { return _next; }
70
bool is_equal(const Klass* k) { return k == _klass; }
71
Klass* klass() const { return _klass; }
72
uint64_t count() const { return _instance_count; }
73
void set_count(uint64_t ct) { _instance_count = ct; }
74
size_t words() const { return _instance_words; }
75
void set_words(size_t wds) { _instance_words = wds; }
76
void set_index(int64_t index) { _index = index; }
77
int64_t index() const { return _index; }
78
GrowableArray<KlassInfoEntry*>* subclasses() const { return _subclasses; }
79
void add_subclass(KlassInfoEntry* cie);
80
void set_do_print(bool do_print) { _do_print = do_print; }
81
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;
96
KlassInfoEntry* list() { return _list; }
97
void set_list(KlassInfoEntry* l) { _list = l; }
98
public:
99
KlassInfoEntry* lookup(Klass* k);
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);
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;
151
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
156
template <class T> static int count_bytes(T* x) {
157
return (HeapWordSize * ((x) ? (x)->size() : 0));
158
}
159
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
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
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
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:
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
250
uintx missed_count() const {
251
return _missed_count;
252
}
253
254
bool success() {
255
return _success;
256
}
257
258
virtual void work(uint worker_id);
259
};
260
261
#endif // SHARE_MEMORY_HEAPINSPECTION_HPP
262
263