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