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