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