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