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