53 int count = (int)_classStack.size();
54 int i = count;
55
56 // Pop all jclasses, fill backwards
57 while (!_classStack.is_empty()) {
58 result_list[--i] = _classStack.pop();
59 }
60
61 // Return the number of elements written
62 return count;
63 }
64
65 // Return current size of the Stack
66 int get_count() {
67 return (int)_classStack.size();
68 }
69 };
70
71 // The closure for GetClassLoaderClasses
72 class JvmtiGetLoadedClassesClosure : public StackObj {
73 // Since the SystemDictionary::classes_do callback
74 // doesn't pass a closureData pointer,
75 // we use a thread-local slot to hold a pointer to
76 // a stack allocated instance of this structure.
77 private:
78 jobject _initiatingLoader;
79 int _count;
80 Handle* _list;
81 int _index;
82
83 private:
84 // Getting and setting the thread local pointer
85 static JvmtiGetLoadedClassesClosure* get_this() {
86 JvmtiGetLoadedClassesClosure* result = NULL;
87 JavaThread* thread = JavaThread::current();
88 result = thread->get_jvmti_get_loaded_classes_closure();
89 return result;
90 }
91 static void set_this(JvmtiGetLoadedClassesClosure* that) {
92 JavaThread* thread = JavaThread::current();
93 thread->set_jvmti_get_loaded_classes_closure(that);
186 assert(Universe::heap()->is_in(get_element(i)()), "check fails");
187 }
188 }
189 #endif
190
191 // Public methods that get called within the scope of the closure
192 void allocate() {
193 _list = NEW_C_HEAP_ARRAY(Handle, _count, mtInternal);
194 assert(_list != NULL, "Out of memory");
195 if (_list == NULL) {
196 _count = 0;
197 }
198 }
199
200 void extract(JvmtiEnv *env, jclass* result) {
201 for (int index = 0; index < _count; index += 1) {
202 result[index] = (jclass) env->jni_reference(get_element(index));
203 }
204 }
205
206 static void increment_with_loader(Klass* k, ClassLoaderData* loader_data) {
207 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
208 oop class_loader = loader_data->class_loader();
209 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
210 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
211 that->set_count(that->get_count() + 1);
212 }
213 }
214 }
215
216 static void add_with_loader(Klass* k, ClassLoaderData* loader_data) {
217 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
218 if (that->available()) {
219 oop class_loader = loader_data->class_loader();
220 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
221 Thread *thread = Thread::current();
222 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
223 Handle mirror(thread, l->java_mirror());
224 that->set_element(that->get_index(), mirror);
225 that->set_index(that->get_index() + 1);
226 }
227 }
228 }
229 }
230
231 // increment the count for the given basic type array class (and any
232 // multi-dimensional arrays). For example, for [B we check for
233 // [[B, [[[B, .. and the count is incremented for each one that exists.
234 static void increment_for_basic_type_arrays(Klass* k) {
235 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
236 assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
268 ClassLoaderDataGraph::loaded_classes_do(&closure);
269 }
270
271 // Return results by extracting the collected contents into a list
272 // allocated via JvmtiEnv
273 jclass* result_list;
274 jvmtiError error = env->Allocate(closure.get_count() * sizeof(jclass),
275 (unsigned char**)&result_list);
276
277 if (error == JVMTI_ERROR_NONE) {
278 int count = closure.extract(result_list);
279 *classCountPtr = count;
280 *classesPtr = result_list;
281 }
282 return error;
283 }
284
285 jvmtiError
286 JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
287 jint* classCountPtr, jclass** classesPtr) {
288 // Since SystemDictionary::classes_do only takes a function pointer
289 // and doesn't call back with a closure data pointer,
290 // we can only pass static methods.
291 JvmtiGetLoadedClassesClosure closure(initiatingLoader);
292 {
293 // To get a consistent list of classes we need MultiArray_lock to ensure
294 // array classes aren't created, and SystemDictionary_lock to ensure that
295 // classes aren't added to the system dictionary,
296 MutexLocker ma(MultiArray_lock);
297 MutexLocker sd(SystemDictionary_lock);
298 // First, count the classes in the system dictionary which have this loader recorded
299 // as an initiating loader. For basic type arrays this information is not recorded
300 // so GetClassLoaderClasses will return all of the basic type arrays. This is okay
301 // because the defining loader for basic type arrays is always the boot class loader
302 // and these classes are "visible" to all loaders.
303 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment_with_loader);
304 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment_for_basic_type_arrays);
305 // Next, fill in the classes
306 closure.allocate();
307 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add_with_loader);
308 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add_for_basic_type_arrays);
309 // Drop the SystemDictionary_lock, so the results could be wrong from here,
310 // but we still have a snapshot.
311 }
312 // Post results
313 jclass* result_list;
314 jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass),
315 (unsigned char**)&result_list);
316 if (err != JVMTI_ERROR_NONE) {
317 return err;
318 }
319 closure.extract(env, result_list);
320 *classCountPtr = closure.get_count();
321 *classesPtr = result_list;
322 return JVMTI_ERROR_NONE;
323 }
|
53 int count = (int)_classStack.size();
54 int i = count;
55
56 // Pop all jclasses, fill backwards
57 while (!_classStack.is_empty()) {
58 result_list[--i] = _classStack.pop();
59 }
60
61 // Return the number of elements written
62 return count;
63 }
64
65 // Return current size of the Stack
66 int get_count() {
67 return (int)_classStack.size();
68 }
69 };
70
71 // The closure for GetClassLoaderClasses
72 class JvmtiGetLoadedClassesClosure : public StackObj {
73 // Since the ClassLoaderDataGraph::dictionary_all_entries_do callback
74 // doesn't pass a closureData pointer,
75 // we use a thread-local slot to hold a pointer to
76 // a stack allocated instance of this structure.
77 private:
78 jobject _initiatingLoader;
79 int _count;
80 Handle* _list;
81 int _index;
82
83 private:
84 // Getting and setting the thread local pointer
85 static JvmtiGetLoadedClassesClosure* get_this() {
86 JvmtiGetLoadedClassesClosure* result = NULL;
87 JavaThread* thread = JavaThread::current();
88 result = thread->get_jvmti_get_loaded_classes_closure();
89 return result;
90 }
91 static void set_this(JvmtiGetLoadedClassesClosure* that) {
92 JavaThread* thread = JavaThread::current();
93 thread->set_jvmti_get_loaded_classes_closure(that);
186 assert(Universe::heap()->is_in(get_element(i)()), "check fails");
187 }
188 }
189 #endif
190
191 // Public methods that get called within the scope of the closure
192 void allocate() {
193 _list = NEW_C_HEAP_ARRAY(Handle, _count, mtInternal);
194 assert(_list != NULL, "Out of memory");
195 if (_list == NULL) {
196 _count = 0;
197 }
198 }
199
200 void extract(JvmtiEnv *env, jclass* result) {
201 for (int index = 0; index < _count; index += 1) {
202 result[index] = (jclass) env->jni_reference(get_element(index));
203 }
204 }
205
206 static void increment_with_loader(InstanceKlass* k, ClassLoaderData* loader_data) {
207 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
208 oop class_loader = loader_data->class_loader();
209 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
210 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
211 that->set_count(that->get_count() + 1);
212 }
213 }
214 }
215
216 static void add_with_loader(InstanceKlass* k, ClassLoaderData* loader_data) {
217 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
218 if (that->available()) {
219 oop class_loader = loader_data->class_loader();
220 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
221 Thread *thread = Thread::current();
222 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
223 Handle mirror(thread, l->java_mirror());
224 that->set_element(that->get_index(), mirror);
225 that->set_index(that->get_index() + 1);
226 }
227 }
228 }
229 }
230
231 // increment the count for the given basic type array class (and any
232 // multi-dimensional arrays). For example, for [B we check for
233 // [[B, [[[B, .. and the count is incremented for each one that exists.
234 static void increment_for_basic_type_arrays(Klass* k) {
235 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
236 assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
268 ClassLoaderDataGraph::loaded_classes_do(&closure);
269 }
270
271 // Return results by extracting the collected contents into a list
272 // allocated via JvmtiEnv
273 jclass* result_list;
274 jvmtiError error = env->Allocate(closure.get_count() * sizeof(jclass),
275 (unsigned char**)&result_list);
276
277 if (error == JVMTI_ERROR_NONE) {
278 int count = closure.extract(result_list);
279 *classCountPtr = count;
280 *classesPtr = result_list;
281 }
282 return error;
283 }
284
285 jvmtiError
286 JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
287 jint* classCountPtr, jclass** classesPtr) {
288 // Since ClassLoaderDataGraph::dictionary_all_entries_do only takes a function pointer
289 // and doesn't call back with a closure data pointer,
290 // we can only pass static methods.
291 JvmtiGetLoadedClassesClosure closure(initiatingLoader);
292 {
293 // To get a consistent list of classes we need MultiArray_lock to ensure
294 // array classes aren't created, and SystemDictionary_lock to ensure that
295 // classes aren't added to the class loader data dictionaries.
296 MutexLocker ma(MultiArray_lock);
297 MutexLocker sd(SystemDictionary_lock);
298 // First, count the classes in the class loader data dictionaries which have this loader recorded
299 // as an initiating loader. For basic type arrays this information is not recorded
300 // so GetClassLoaderClasses will return all of the basic type arrays. This is okay
301 // because the defining loader for basic type arrays is always the boot class loader
302 // and these classes are "visible" to all loaders.
303 ClassLoaderDataGraph::dictionary_all_entries_do(&JvmtiGetLoadedClassesClosure::increment_with_loader);
304 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment_for_basic_type_arrays);
305 // Next, fill in the classes
306 closure.allocate();
307 ClassLoaderDataGraph::dictionary_all_entries_do(&JvmtiGetLoadedClassesClosure::add_with_loader);
308 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add_for_basic_type_arrays);
309 // Drop the SystemDictionary_lock, so the results could be wrong from here,
310 // but we still have a snapshot.
311 }
312 // Post results
313 jclass* result_list;
314 jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass),
315 (unsigned char**)&result_list);
316 if (err != JVMTI_ERROR_NONE) {
317 return err;
318 }
319 closure.extract(env, result_list);
320 *classCountPtr = closure.get_count();
321 *classesPtr = result_list;
322 return JVMTI_ERROR_NONE;
323 }
|