hotspot/src/share/vm/prims/jvmtiGetLoadedClasses.cpp
changeset 21183 e148e499e5cd
parent 14488 ab48109f7d1b
child 22234 da823d78ad65
equal deleted inserted replaced
21083:45b520adf92d 21183:e148e499e5cd
    27 #include "memory/universe.inline.hpp"
    27 #include "memory/universe.inline.hpp"
    28 #include "prims/jvmtiGetLoadedClasses.hpp"
    28 #include "prims/jvmtiGetLoadedClasses.hpp"
    29 #include "runtime/thread.hpp"
    29 #include "runtime/thread.hpp"
    30 
    30 
    31 
    31 
    32 
    32 // The closure for GetLoadedClasses
    33 // The closure for GetLoadedClasses and GetClassLoaderClasses
    33 class LoadedClassesClosure : public KlassClosure {
       
    34 private:
       
    35   Stack<jclass, mtInternal> _classStack;
       
    36   JvmtiEnv* _env;
       
    37 
       
    38 public:
       
    39   LoadedClassesClosure(JvmtiEnv* env) {
       
    40     _env = env;
       
    41   }
       
    42 
       
    43   void do_klass(Klass* k) {
       
    44     // Collect all jclasses
       
    45     _classStack.push((jclass) _env->jni_reference(k->java_mirror()));
       
    46   }
       
    47 
       
    48   int extract(jclass* result_list) {
       
    49     // The size of the Stack will be 0 after extract, so get it here
       
    50     int count = (int)_classStack.size();
       
    51     int i = count;
       
    52 
       
    53     // Pop all jclasses, fill backwards
       
    54     while (!_classStack.is_empty()) {
       
    55       result_list[--i] = _classStack.pop();
       
    56     }
       
    57 
       
    58     // Return the number of elements written
       
    59     return count;
       
    60   }
       
    61 
       
    62   // Return current size of the Stack
       
    63   int get_count() {
       
    64     return (int)_classStack.size();
       
    65   }
       
    66 };
       
    67 
       
    68 // The closure for GetClassLoaderClasses
    34 class JvmtiGetLoadedClassesClosure : public StackObj {
    69 class JvmtiGetLoadedClassesClosure : public StackObj {
    35   // Since the SystemDictionary::classes_do callback
    70   // Since the SystemDictionary::classes_do callback
    36   // doesn't pass a closureData pointer,
    71   // doesn't pass a closureData pointer,
    37   // we use a thread-local slot to hold a pointer to
    72   // we use a thread-local slot to hold a pointer to
    38   // a stack allocated instance of this structure.
    73   // a stack allocated instance of this structure.
   163     for (int index = 0; index < _count; index += 1) {
   198     for (int index = 0; index < _count; index += 1) {
   164       result[index] = (jclass) env->jni_reference(get_element(index));
   199       result[index] = (jclass) env->jni_reference(get_element(index));
   165     }
   200     }
   166   }
   201   }
   167 
   202 
   168   // Finally, the static methods that are the callbacks
       
   169   static void increment(Klass* k) {
       
   170     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
       
   171     if (that->get_initiatingLoader() == NULL) {
       
   172       for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
       
   173         that->set_count(that->get_count() + 1);
       
   174       }
       
   175     } else if (k != NULL) {
       
   176       // if initiating loader not null, just include the instance with 1 dimension
       
   177       that->set_count(that->get_count() + 1);
       
   178     }
       
   179   }
       
   180 
       
   181   static void increment_with_loader(Klass* k, ClassLoaderData* loader_data) {
   203   static void increment_with_loader(Klass* k, ClassLoaderData* loader_data) {
   182     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   204     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   183     oop class_loader = loader_data->class_loader();
   205     oop class_loader = loader_data->class_loader();
   184     if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
   206     if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
   185       for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
   207       for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
   191   static void prim_array_increment_with_loader(Klass* array, ClassLoaderData* loader_data) {
   213   static void prim_array_increment_with_loader(Klass* array, ClassLoaderData* loader_data) {
   192     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   214     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   193     oop class_loader = loader_data->class_loader();
   215     oop class_loader = loader_data->class_loader();
   194     if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
   216     if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
   195       that->set_count(that->get_count() + 1);
   217       that->set_count(that->get_count() + 1);
   196     }
       
   197   }
       
   198 
       
   199   static void add(Klass* k) {
       
   200     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
       
   201     if (that->available()) {
       
   202       if (that->get_initiatingLoader() == NULL) {
       
   203         for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
       
   204           oop mirror = l->java_mirror();
       
   205           that->set_element(that->get_index(), mirror);
       
   206           that->set_index(that->get_index() + 1);
       
   207         }
       
   208       } else if (k != NULL) {
       
   209         // if initiating loader not null, just include the instance with 1 dimension
       
   210         oop mirror = k->java_mirror();
       
   211         that->set_element(that->get_index(), mirror);
       
   212         that->set_index(that->get_index() + 1);
       
   213       }
       
   214     }
   218     }
   215   }
   219   }
   216 
   220 
   217   static void add_with_loader(Klass* k, ClassLoaderData* loader_data) {
   221   static void add_with_loader(Klass* k, ClassLoaderData* loader_data) {
   218     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   222     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   253 };
   257 };
   254 
   258 
   255 
   259 
   256 jvmtiError
   260 jvmtiError
   257 JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {
   261 JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {
   258   // Since SystemDictionary::classes_do only takes a function pointer
   262 
   259   // and doesn't call back with a closure data pointer,
   263   LoadedClassesClosure closure(env);
   260   // we can only pass static methods.
       
   261 
       
   262   JvmtiGetLoadedClassesClosure closure;
       
   263   {
   264   {
   264     // To get a consistent list of classes we need MultiArray_lock to ensure
   265     // To get a consistent list of classes we need MultiArray_lock to ensure
   265     // array classes aren't created, and SystemDictionary_lock to ensure that
   266     // array classes aren't created.
   266     // classes aren't added to the system dictionary,
       
   267     MutexLocker ma(MultiArray_lock);
   267     MutexLocker ma(MultiArray_lock);
   268     MutexLocker sd(SystemDictionary_lock);
   268 
   269 
   269     // Iterate through all classes in ClassLoaderDataGraph
   270     // First, count the classes
   270     // and collect them using the LoadedClassesClosure
   271     SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment);
   271     ClassLoaderDataGraph::loaded_classes_do(&closure);
   272     Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment);
   272   }
   273     // Next, fill in the classes
   273 
   274     closure.allocate();
   274   // Return results by extracting the collected contents into a list
   275     SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add);
   275   // allocated via JvmtiEnv
   276     Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add);
       
   277     // Drop the SystemDictionary_lock, so the results could be wrong from here,
       
   278     // but we still have a snapshot.
       
   279   }
       
   280   // Post results
       
   281   jclass* result_list;
   276   jclass* result_list;
   282   jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass),
   277   jvmtiError error = env->Allocate(closure.get_count() * sizeof(jclass),
   283                                  (unsigned char**)&result_list);
   278                                (unsigned char**)&result_list);
   284   if (err != JVMTI_ERROR_NONE) {
   279 
   285     return err;
   280   if (error == JVMTI_ERROR_NONE) {
   286   }
   281     int count = closure.extract(result_list);
   287   closure.extract(env, result_list);
   282     *classCountPtr = count;
   288   *classCountPtr = closure.get_count();
   283     *classesPtr = result_list;
   289   *classesPtr = result_list;
   284   }
   290   return JVMTI_ERROR_NONE;
   285   return error;
   291 }
   286 }
   292 
   287 
   293 jvmtiError
   288 jvmtiError
   294 JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
   289 JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
   295                                              jint* classCountPtr, jclass** classesPtr) {
   290                                              jint* classCountPtr, jclass** classesPtr) {