src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
changeset 51530 1f0b605bdc28
parent 51334 cc2c79d22508
child 51608 625a5bdde0c5
equal deleted inserted replaced
51529:a716460217ed 51530:1f0b605bdc28
    21  * questions.
    21  * questions.
    22  *
    22  *
    23  */
    23  */
    24 
    24 
    25 #include "precompiled.hpp"
    25 #include "precompiled.hpp"
       
    26 #include "classfile/dictionary.hpp"
    26 #include "classfile/classLoaderData.inline.hpp"
    27 #include "classfile/classLoaderData.inline.hpp"
    27 #include "classfile/systemDictionary.hpp"
    28 #include "classfile/systemDictionary.hpp"
    28 #include "gc/shared/collectedHeap.hpp"
    29 #include "gc/shared/collectedHeap.hpp"
    29 #include "memory/universe.hpp"
    30 #include "memory/universe.hpp"
    30 #include "prims/jvmtiGetLoadedClasses.hpp"
    31 #include "prims/jvmtiGetLoadedClasses.hpp"
    37 class LoadedClassesClosure : public KlassClosure {
    38 class LoadedClassesClosure : public KlassClosure {
    38 private:
    39 private:
    39   Stack<jclass, mtInternal> _classStack;
    40   Stack<jclass, mtInternal> _classStack;
    40   JvmtiEnv* _env;
    41   JvmtiEnv* _env;
    41   Thread*   _cur_thread;
    42   Thread*   _cur_thread;
    42 
    43   bool      _dictionary_walk;
    43 public:
       
    44   LoadedClassesClosure(Thread* thread, JvmtiEnv* env) : _env(env), _cur_thread(thread) {
       
    45     assert(_cur_thread == Thread::current(), "must be current thread");
       
    46   }
       
    47 
       
    48   void do_klass(Klass* k) {
       
    49     // Collect all jclasses
       
    50     _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror())));
       
    51   }
       
    52 
    44 
    53   int extract(jclass* result_list) {
    45   int extract(jclass* result_list) {
    54     // The size of the Stack will be 0 after extract, so get it here
    46     // The size of the Stack will be 0 after extract, so get it here
    55     int count = (int)_classStack.size();
    47     int count = (int)_classStack.size();
    56     int i = count;
    48     int i = count;
    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 }