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