< prev index next >

src/share/vm/prims/jvmtiGetLoadedClasses.cpp

Print this page




  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 }
< prev index next >