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