jvmtiGetLoadedClasses.cpp revision 5776:de6a9e811145
1193323Sed/* 2193323Sed * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3193323Sed * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4193323Sed * 5193323Sed * This code is free software; you can redistribute it and/or modify it 6193323Sed * under the terms of the GNU General Public License version 2 only, as 7193323Sed * published by the Free Software Foundation. 8193323Sed * 9193323Sed * This code is distributed in the hope that it will be useful, but WITHOUT 10193323Sed * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11193323Sed * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12193323Sed * version 2 for more details (a copy is included in the LICENSE file that 13193323Sed * accompanied this code). 14193323Sed * 15193323Sed * You should have received a copy of the GNU General Public License version 16193323Sed * 2 along with this work; if not, write to the Free Software Foundation, 17234353Sdim * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18218893Sdim * 19239462Sdim * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20249423Sdim * or visit www.oracle.com if you need additional information or have any 21218893Sdim * questions. 22218893Sdim * 23218893Sdim */ 24218893Sdim 25193323Sed#include "precompiled.hpp" 26249423Sdim#include "classfile/systemDictionary.hpp" 27193323Sed#include "memory/universe.inline.hpp" 28193323Sed#include "prims/jvmtiGetLoadedClasses.hpp" 29218893Sdim#include "runtime/thread.hpp" 30249423Sdim 31193323Sed 32193323Sed// The closure for GetLoadedClasses 33193323Sedclass LoadedClassesClosure : public KlassClosure { 34193323Sedprivate: 35193323Sed Stack<jclass, mtInternal> _classStack; 36263508Sdim JvmtiEnv* _env; 37249423Sdim 38249423Sdimpublic: 39193323Sed LoadedClassesClosure(JvmtiEnv* env) { 40249423Sdim _env = env; 41249423Sdim } 42243830Sdim 43249423Sdim void do_klass(Klass* k) { 44193323Sed // Collect all jclasses 45193323Sed _classStack.push((jclass) _env->jni_reference(k->java_mirror())); 46193323Sed } 47193323Sed 48193323Sed int extract(jclass* result_list) { 49193323Sed // The size of the Stack will be 0 after extract, so get it here 50210299Sed int count = (int)_classStack.size(); 51193323Sed int i = count; 52193323Sed 53193323Sed // Pop all jclasses, fill backwards 54221345Sdim while (!_classStack.is_empty()) { 55221345Sdim result_list[--i] = _classStack.pop(); 56221345Sdim } 57221345Sdim 58193323Sed // Return the number of elements written 59193323Sed return count; 60193323Sed } 61193323Sed 62193323Sed // Return current size of the Stack 63193323Sed int get_count() { 64193323Sed return (int)_classStack.size(); 65193323Sed } 66210299Sed}; 67210299Sed 68210299Sed// The closure for GetClassLoaderClasses 69210299Sedclass JvmtiGetLoadedClassesClosure : public StackObj { 70210299Sed // Since the SystemDictionary::classes_do callback 71210299Sed // doesn't pass a closureData pointer, 72210299Sed // we use a thread-local slot to hold a pointer to 73249423Sdim // a stack allocated instance of this structure. 74249423Sdim private: 75249423Sdim jobject _initiatingLoader; 76249423Sdim int _count; 77249423Sdim Handle* _list; 78210299Sed int _index; 79210299Sed 80249423Sdim private: 81249423Sdim // Getting and setting the thread local pointer 82249423Sdim static JvmtiGetLoadedClassesClosure* get_this() { 83249423Sdim JvmtiGetLoadedClassesClosure* result = NULL; 84249423Sdim JavaThread* thread = JavaThread::current(); 85249423Sdim result = thread->get_jvmti_get_loaded_classes_closure(); 86193323Sed return result; 87210299Sed } 88193323Sed static void set_this(JvmtiGetLoadedClassesClosure* that) { 89193323Sed JavaThread* thread = JavaThread::current(); 90221345Sdim thread->set_jvmti_get_loaded_classes_closure(that); 91221345Sdim } 92193323Sed 93210299Sed public: 94243830Sdim // Constructor/Destructor 95210299Sed JvmtiGetLoadedClassesClosure() { 96210299Sed JvmtiGetLoadedClassesClosure* that = get_this(); 97193323Sed assert(that == NULL, "JvmtiGetLoadedClassesClosure in use"); 98243830Sdim _initiatingLoader = NULL; 99243830Sdim _count = 0; 100221345Sdim _list = NULL; 101221345Sdim _index = 0; 102193323Sed set_this(this); 103193323Sed } 104193323Sed 105193323Sed JvmtiGetLoadedClassesClosure(jobject initiatingLoader) { 106223017Sdim JvmtiGetLoadedClassesClosure* that = get_this(); 107206274Srdivacky assert(that == NULL, "JvmtiGetLoadedClassesClosure in use"); 108221345Sdim _initiatingLoader = initiatingLoader; 109221345Sdim _count = 0; 110249423Sdim _list = NULL; 111249423Sdim _index = 0; 112193323Sed set_this(this); 113193323Sed } 114193323Sed 115193323Sed ~JvmtiGetLoadedClassesClosure() { 116193323Sed JvmtiGetLoadedClassesClosure* that = get_this(); 117206274Srdivacky assert(that != NULL, "JvmtiGetLoadedClassesClosure not found"); 118210299Sed set_this(NULL); 119210299Sed _initiatingLoader = NULL; 120210299Sed _count = 0; 121210299Sed if (_list != NULL) { 122210299Sed FreeHeap(_list); 123210299Sed _list = NULL; 124193323Sed } 125193323Sed _index = 0; 126193323Sed } 127210299Sed 128210299Sed // Accessors. 129210299Sed jobject get_initiatingLoader() { 130193323Sed return _initiatingLoader; 131199481Srdivacky } 132210299Sed 133210299Sed int get_count() { 134210299Sed return _count; 135210299Sed } 136210299Sed 137210299Sed void set_count(int value) { 138210299Sed _count = value; 139210299Sed } 140210299Sed 141210299Sed Handle* get_list() { 142210299Sed return _list; 143210299Sed } 144210299Sed 145210299Sed void set_list(Handle* value) { 146210299Sed _list = value; 147210299Sed } 148221345Sdim 149193323Sed int get_index() { 150193323Sed return _index; 151193323Sed } 152193323Sed 153193323Sed void set_index(int value) { 154193323Sed _index = value; 155210299Sed } 156193323Sed 157193323Sed Handle get_element(int index) { 158210299Sed if ((_list != NULL) && (index < _count)) { 159193323Sed return _list[index]; 160193323Sed } else { 161193323Sed assert(false, "empty get_element"); 162193323Sed return Handle(); 163193323Sed } 164193323Sed } 165193323Sed 166193323Sed void set_element(int index, Handle value) { 167218893Sdim if ((_list != NULL) && (index < _count)) { 168218893Sdim _list[index] = value; 169218893Sdim } else { 170199481Srdivacky assert(false, "bad set_element"); 171218893Sdim } 172218893Sdim } 173193323Sed 174193323Sed // Other predicates 175193323Sed bool available() { 176193323Sed return (_list != NULL); 177193323Sed } 178193323Sed 179193323Sed#ifdef ASSERT 180263508Sdim // For debugging. 181249423Sdim void check(int limit) { 182249423Sdim for (int i = 0; i < limit; i += 1) { 183249423Sdim assert(Universe::heap()->is_in(get_element(i)()), "check fails"); 184249423Sdim } 185210299Sed } 186249423Sdim#endif 187249423Sdim 188249423Sdim // Public methods that get called within the scope of the closure 189221345Sdim void allocate() { 190249423Sdim _list = NEW_C_HEAP_ARRAY(Handle, _count, mtInternal); 191249423Sdim assert(_list != NULL, "Out of memory"); 192249423Sdim if (_list == NULL) { 193221345Sdim _count = 0; 194249423Sdim } 195249423Sdim } 196193323Sed 197243830Sdim void extract(JvmtiEnv *env, jclass* result) { 198249423Sdim for (int index = 0; index < _count; index += 1) { 199249423Sdim result[index] = (jclass) env->jni_reference(get_element(index)); 200249423Sdim } 201249423Sdim } 202249423Sdim 203249423Sdim static void increment_with_loader(Klass* k, ClassLoaderData* loader_data) { 204249423Sdim JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); 205249423Sdim oop class_loader = loader_data->class_loader(); 206249423Sdim if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) { 207249423Sdim for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { 208249423Sdim that->set_count(that->get_count() + 1); 209249423Sdim } 210249423Sdim } 211249423Sdim } 212249423Sdim 213249423Sdim static void prim_array_increment_with_loader(Klass* array, ClassLoaderData* loader_data) { 214243830Sdim JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); 215221345Sdim oop class_loader = loader_data->class_loader(); 216221345Sdim if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) { 217193323Sed that->set_count(that->get_count() + 1); 218193323Sed } 219193323Sed } 220263508Sdim 221243830Sdim static void add_with_loader(Klass* k, ClassLoaderData* loader_data) { 222243830Sdim JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); 223243830Sdim if (that->available()) { 224243830Sdim oop class_loader = loader_data->class_loader(); 225243830Sdim if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) { 226243830Sdim for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { 227243830Sdim oop mirror = l->java_mirror(); 228243830Sdim that->set_element(that->get_index(), mirror); 229243830Sdim that->set_index(that->get_index() + 1); 230243830Sdim } 231243830Sdim } 232243830Sdim } 233243830Sdim } 234243830Sdim 235243830Sdim // increment the count for the given basic type array class (and any 236243830Sdim // multi-dimensional arrays). For example, for [B we check for 237243830Sdim // [[B, [[[B, .. and the count is incremented for each one that exists. 238243830Sdim static void increment_for_basic_type_arrays(Klass* k) { 239243830Sdim JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); 240243830Sdim assert(that != NULL, "no JvmtiGetLoadedClassesClosure"); 241263508Sdim for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { 242263508Sdim that->set_count(that->get_count() + 1); 243263508Sdim } 244263508Sdim } 245263508Sdim 246218893Sdim // add the basic type array class and its multi-dimensional array classes to the list 247221345Sdim static void add_for_basic_type_arrays(Klass* k) { 248221345Sdim JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); 249218893Sdim assert(that != NULL, "no JvmtiGetLoadedClassesClosure"); 250263508Sdim assert(that->available(), "no list"); 251263508Sdim for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { 252263508Sdim oop mirror = l->java_mirror(); 253263508Sdim that->set_element(that->get_index(), mirror); 254210299Sed that->set_index(that->get_index() + 1); 255210299Sed } 256263508Sdim } 257263508Sdim}; 258263508Sdim 259263508Sdim 260239462SdimjvmtiError 261263508SdimJvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) { 262263508Sdim 263263508Sdim LoadedClassesClosure closure(env); 264263508Sdim { 265263508Sdim // To get a consistent list of classes we need MultiArray_lock to ensure 266263508Sdim // array classes aren't created. 267263508Sdim MutexLocker ma(MultiArray_lock); 268223017Sdim 269263508Sdim // Iterate through all classes in ClassLoaderDataGraph 270263508Sdim // and collect them using the LoadedClassesClosure 271218893Sdim ClassLoaderDataGraph::loaded_classes_do(&closure); 272218893Sdim } 273218893Sdim 274218893Sdim // Return results by extracting the collected contents into a list 275221345Sdim // allocated via JvmtiEnv 276221345Sdim jclass* result_list; 277221345Sdim jvmtiError error = env->Allocate(closure.get_count() * sizeof(jclass), 278221345Sdim (unsigned char**)&result_list); 279221345Sdim 280221345Sdim if (error == JVMTI_ERROR_NONE) { 281221345Sdim int count = closure.extract(result_list); 282221345Sdim *classCountPtr = count; 283263508Sdim *classesPtr = result_list; 284221345Sdim } 285221345Sdim return error; 286221345Sdim} 287221345Sdim 288221345SdimjvmtiError 289221345SdimJvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader, 290193323Sed jint* classCountPtr, jclass** classesPtr) { 291193323Sed // Since SystemDictionary::classes_do only takes a function pointer 292221345Sdim // and doesn't call back with a closure data pointer, 293221345Sdim // we can only pass static methods. 294221345Sdim JvmtiGetLoadedClassesClosure closure(initiatingLoader); 295263508Sdim { 296263508Sdim // To get a consistent list of classes we need MultiArray_lock to ensure 297263508Sdim // array classes aren't created, and SystemDictionary_lock to ensure that 298263508Sdim // classes aren't added to the system dictionary, 299263508Sdim MutexLocker ma(MultiArray_lock); 300193323Sed MutexLocker sd(SystemDictionary_lock); 301218893Sdim // First, count the classes in the system dictionary which have this loader recorded 302221345Sdim // as an initiating loader. For basic type arrays this information is not recorded 303221345Sdim // so GetClassLoaderClasses will return all of the basic type arrays. This is okay 304221345Sdim // because the defining loader for basic type arrays is always the boot class loader 305221345Sdim // and these classes are "visible" to all loaders. 306221345Sdim SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment_with_loader); 307221345Sdim Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment_for_basic_type_arrays); 308218893Sdim // Next, fill in the classes 309263508Sdim closure.allocate(); 310263508Sdim SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add_with_loader); 311263508Sdim Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add_for_basic_type_arrays); 312263508Sdim // Drop the SystemDictionary_lock, so the results could be wrong from here, 313263508Sdim // but we still have a snapshot. 314263508Sdim } 315263508Sdim // Post results 316263508Sdim jclass* result_list; 317263508Sdim jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass), 318221345Sdim (unsigned char**)&result_list); 319221345Sdim if (err != JVMTI_ERROR_NONE) { 320221345Sdim return err; 321221345Sdim } 322221345Sdim closure.extract(env, result_list); 323221345Sdim *classCountPtr = closure.get_count(); 324221345Sdim *classesPtr = result_list; 325221345Sdim return JVMTI_ERROR_NONE; 326263508Sdim} 327263508Sdim