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 }