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