Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-aarch32-jdk8u
Path: blob/jdk8u272-b10-aarch32-20201026/hotspot/src/share/vm/prims/jvmtiGetLoadedClasses.cpp
48773 views
1
/*
2
* Copyright (c) 2003, 2018, 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
#include "precompiled.hpp"
26
#include "classfile/systemDictionary.hpp"
27
#include "memory/universe.inline.hpp"
28
#include "prims/jvmtiGetLoadedClasses.hpp"
29
#include "runtime/thread.hpp"
30
#if INCLUDE_ALL_GCS
31
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
32
#endif
33
34
35
// The closure for GetLoadedClasses
36
class LoadedClassesClosure : public KlassClosure {
37
private:
38
Stack<jclass, mtInternal> _classStack;
39
JvmtiEnv* _env;
40
41
// Tell the GC to keep this klass alive
42
static void ensure_klass_alive(oop o) {
43
// A klass that was previously considered dead can be looked up in the
44
// CLD/SD, and its _java_mirror or _class_loader can be stored in a root
45
// or a reachable object making it alive again. The SATB part of G1 needs
46
// to get notified about this potential resurrection, otherwise the marking
47
// might not find the object.
48
#if INCLUDE_ALL_GCS
49
if (UseG1GC && o != NULL) {
50
G1SATBCardTableModRefBS::enqueue(o);
51
}
52
#endif
53
}
54
55
public:
56
LoadedClassesClosure(JvmtiEnv* env) {
57
_env = env;
58
}
59
60
void do_klass(Klass* k) {
61
// Collect all jclasses
62
_classStack.push((jclass) _env->jni_reference(k->java_mirror()));
63
ensure_klass_alive(k->java_mirror());
64
}
65
66
int extract(jclass* result_list) {
67
// The size of the Stack will be 0 after extract, so get it here
68
int count = (int)_classStack.size();
69
int i = count;
70
71
// Pop all jclasses, fill backwards
72
while (!_classStack.is_empty()) {
73
result_list[--i] = _classStack.pop();
74
}
75
76
// Return the number of elements written
77
return count;
78
}
79
80
// Return current size of the Stack
81
int get_count() {
82
return (int)_classStack.size();
83
}
84
};
85
86
// The closure for GetClassLoaderClasses
87
class JvmtiGetLoadedClassesClosure : public StackObj {
88
// Since the SystemDictionary::classes_do callback
89
// doesn't pass a closureData pointer,
90
// we use a thread-local slot to hold a pointer to
91
// a stack allocated instance of this structure.
92
private:
93
jobject _initiatingLoader;
94
int _count;
95
Handle* _list;
96
int _index;
97
98
private:
99
// Getting and setting the thread local pointer
100
static JvmtiGetLoadedClassesClosure* get_this() {
101
JvmtiGetLoadedClassesClosure* result = NULL;
102
JavaThread* thread = JavaThread::current();
103
result = thread->get_jvmti_get_loaded_classes_closure();
104
return result;
105
}
106
static void set_this(JvmtiGetLoadedClassesClosure* that) {
107
JavaThread* thread = JavaThread::current();
108
thread->set_jvmti_get_loaded_classes_closure(that);
109
}
110
111
public:
112
// Constructor/Destructor
113
JvmtiGetLoadedClassesClosure() {
114
JvmtiGetLoadedClassesClosure* that = get_this();
115
assert(that == NULL, "JvmtiGetLoadedClassesClosure in use");
116
_initiatingLoader = NULL;
117
_count = 0;
118
_list = NULL;
119
_index = 0;
120
set_this(this);
121
}
122
123
JvmtiGetLoadedClassesClosure(jobject initiatingLoader) {
124
JvmtiGetLoadedClassesClosure* that = get_this();
125
assert(that == NULL, "JvmtiGetLoadedClassesClosure in use");
126
_initiatingLoader = initiatingLoader;
127
_count = 0;
128
_list = NULL;
129
_index = 0;
130
set_this(this);
131
}
132
133
~JvmtiGetLoadedClassesClosure() {
134
JvmtiGetLoadedClassesClosure* that = get_this();
135
assert(that != NULL, "JvmtiGetLoadedClassesClosure not found");
136
set_this(NULL);
137
_initiatingLoader = NULL;
138
_count = 0;
139
if (_list != NULL) {
140
FreeHeap(_list);
141
_list = NULL;
142
}
143
_index = 0;
144
}
145
146
// Accessors.
147
jobject get_initiatingLoader() {
148
return _initiatingLoader;
149
}
150
151
int get_count() {
152
return _count;
153
}
154
155
void set_count(int value) {
156
_count = value;
157
}
158
159
Handle* get_list() {
160
return _list;
161
}
162
163
void set_list(Handle* value) {
164
_list = value;
165
}
166
167
int get_index() {
168
return _index;
169
}
170
171
void set_index(int value) {
172
_index = value;
173
}
174
175
Handle get_element(int index) {
176
if ((_list != NULL) && (index < _count)) {
177
return _list[index];
178
} else {
179
assert(false, "empty get_element");
180
return Handle();
181
}
182
}
183
184
void set_element(int index, Handle value) {
185
if ((_list != NULL) && (index < _count)) {
186
_list[index] = value;
187
} else {
188
assert(false, "bad set_element");
189
}
190
}
191
192
// Other predicates
193
bool available() {
194
return (_list != NULL);
195
}
196
197
#ifdef ASSERT
198
// For debugging.
199
void check(int limit) {
200
for (int i = 0; i < limit; i += 1) {
201
assert(Universe::heap()->is_in(get_element(i)()), "check fails");
202
}
203
}
204
#endif
205
206
// Public methods that get called within the scope of the closure
207
void allocate() {
208
_list = NEW_C_HEAP_ARRAY(Handle, _count, mtInternal);
209
assert(_list != NULL, "Out of memory");
210
if (_list == NULL) {
211
_count = 0;
212
}
213
}
214
215
void extract(JvmtiEnv *env, jclass* result) {
216
for (int index = 0; index < _count; index += 1) {
217
result[index] = (jclass) env->jni_reference(get_element(index));
218
}
219
}
220
221
static void increment_with_loader(Klass* k, ClassLoaderData* loader_data) {
222
JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
223
oop class_loader = loader_data->class_loader();
224
if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
225
for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
226
that->set_count(that->get_count() + 1);
227
}
228
}
229
}
230
231
static void prim_array_increment_with_loader(Klass* array, ClassLoaderData* loader_data) {
232
JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
233
oop class_loader = loader_data->class_loader();
234
if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
235
that->set_count(that->get_count() + 1);
236
}
237
}
238
239
static void add_with_loader(Klass* k, ClassLoaderData* loader_data) {
240
JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
241
if (that->available()) {
242
oop class_loader = loader_data->class_loader();
243
if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
244
for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
245
oop mirror = l->java_mirror();
246
that->set_element(that->get_index(), mirror);
247
that->set_index(that->get_index() + 1);
248
}
249
}
250
}
251
}
252
253
// increment the count for the given basic type array class (and any
254
// multi-dimensional arrays). For example, for [B we check for
255
// [[B, [[[B, .. and the count is incremented for each one that exists.
256
static void increment_for_basic_type_arrays(Klass* k) {
257
JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
258
assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
259
for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
260
that->set_count(that->get_count() + 1);
261
}
262
}
263
264
// add the basic type array class and its multi-dimensional array classes to the list
265
static void add_for_basic_type_arrays(Klass* k) {
266
JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
267
assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
268
assert(that->available(), "no list");
269
for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
270
oop mirror = l->java_mirror();
271
that->set_element(that->get_index(), mirror);
272
that->set_index(that->get_index() + 1);
273
}
274
}
275
};
276
277
278
jvmtiError
279
JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {
280
281
LoadedClassesClosure closure(env);
282
{
283
// To get a consistent list of classes we need MultiArray_lock to ensure
284
// array classes aren't created.
285
MutexLocker ma(MultiArray_lock);
286
287
// Iterate through all classes in ClassLoaderDataGraph
288
// and collect them using the LoadedClassesClosure
289
ClassLoaderDataGraph::loaded_classes_do(&closure);
290
}
291
292
// Return results by extracting the collected contents into a list
293
// allocated via JvmtiEnv
294
jclass* result_list;
295
jvmtiError error = env->Allocate(closure.get_count() * sizeof(jclass),
296
(unsigned char**)&result_list);
297
298
if (error == JVMTI_ERROR_NONE) {
299
int count = closure.extract(result_list);
300
*classCountPtr = count;
301
*classesPtr = result_list;
302
}
303
return error;
304
}
305
306
jvmtiError
307
JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
308
jint* classCountPtr, jclass** classesPtr) {
309
// Since SystemDictionary::classes_do only takes a function pointer
310
// and doesn't call back with a closure data pointer,
311
// we can only pass static methods.
312
JvmtiGetLoadedClassesClosure closure(initiatingLoader);
313
{
314
// To get a consistent list of classes we need MultiArray_lock to ensure
315
// array classes aren't created, and SystemDictionary_lock to ensure that
316
// classes aren't added to the system dictionary,
317
MutexLocker ma(MultiArray_lock);
318
MutexLocker sd(SystemDictionary_lock);
319
// First, count the classes in the system dictionary which have this loader recorded
320
// as an initiating loader. For basic type arrays this information is not recorded
321
// so GetClassLoaderClasses will return all of the basic type arrays. This is okay
322
// because the defining loader for basic type arrays is always the boot class loader
323
// and these classes are "visible" to all loaders.
324
SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment_with_loader);
325
Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment_for_basic_type_arrays);
326
// Next, fill in the classes
327
closure.allocate();
328
SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add_with_loader);
329
Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add_for_basic_type_arrays);
330
// Drop the SystemDictionary_lock, so the results could be wrong from here,
331
// but we still have a snapshot.
332
}
333
// Post results
334
jclass* result_list;
335
jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass),
336
(unsigned char**)&result_list);
337
if (err != JVMTI_ERROR_NONE) {
338
return err;
339
}
340
closure.extract(env, result_list);
341
*classCountPtr = closure.get_count();
342
*classesPtr = result_list;
343
return JVMTI_ERROR_NONE;
344
}
345
346