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