src/share/vm/prims/jvmtiGetLoadedClasses.cpp

Tue, 08 Aug 2017 15:57:29 +0800

author
aoqi
date
Tue, 08 Aug 2017 15:57:29 +0800
changeset 6876
710a3c8b516e
parent 6198
55fb97c4c58d
parent 0
f90c822e73f8
child 9203
53eec13fbaa5
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "classfile/systemDictionary.hpp"
aoqi@0 27 #include "memory/universe.inline.hpp"
aoqi@0 28 #include "prims/jvmtiGetLoadedClasses.hpp"
aoqi@0 29 #include "runtime/thread.hpp"
aoqi@0 30
aoqi@0 31
aoqi@0 32 // The closure for GetLoadedClasses
aoqi@0 33 class LoadedClassesClosure : public KlassClosure {
aoqi@0 34 private:
aoqi@0 35 Stack<jclass, mtInternal> _classStack;
aoqi@0 36 JvmtiEnv* _env;
aoqi@0 37
aoqi@0 38 public:
aoqi@0 39 LoadedClassesClosure(JvmtiEnv* env) {
aoqi@0 40 _env = env;
aoqi@0 41 }
aoqi@0 42
aoqi@0 43 void do_klass(Klass* k) {
aoqi@0 44 // Collect all jclasses
aoqi@0 45 _classStack.push((jclass) _env->jni_reference(k->java_mirror()));
aoqi@0 46 }
aoqi@0 47
aoqi@0 48 int extract(jclass* result_list) {
aoqi@0 49 // The size of the Stack will be 0 after extract, so get it here
aoqi@0 50 int count = (int)_classStack.size();
aoqi@0 51 int i = count;
aoqi@0 52
aoqi@0 53 // Pop all jclasses, fill backwards
aoqi@0 54 while (!_classStack.is_empty()) {
aoqi@0 55 result_list[--i] = _classStack.pop();
aoqi@0 56 }
aoqi@0 57
aoqi@0 58 // Return the number of elements written
aoqi@0 59 return count;
aoqi@0 60 }
aoqi@0 61
aoqi@0 62 // Return current size of the Stack
aoqi@0 63 int get_count() {
aoqi@0 64 return (int)_classStack.size();
aoqi@0 65 }
aoqi@0 66 };
aoqi@0 67
aoqi@0 68 // The closure for GetClassLoaderClasses
aoqi@0 69 class JvmtiGetLoadedClassesClosure : public StackObj {
aoqi@0 70 // Since the SystemDictionary::classes_do callback
aoqi@0 71 // doesn't pass a closureData pointer,
aoqi@0 72 // we use a thread-local slot to hold a pointer to
aoqi@0 73 // a stack allocated instance of this structure.
aoqi@0 74 private:
aoqi@0 75 jobject _initiatingLoader;
aoqi@0 76 int _count;
aoqi@0 77 Handle* _list;
aoqi@0 78 int _index;
aoqi@0 79
aoqi@0 80 private:
aoqi@0 81 // Getting and setting the thread local pointer
aoqi@0 82 static JvmtiGetLoadedClassesClosure* get_this() {
aoqi@0 83 JvmtiGetLoadedClassesClosure* result = NULL;
aoqi@0 84 JavaThread* thread = JavaThread::current();
aoqi@0 85 result = thread->get_jvmti_get_loaded_classes_closure();
aoqi@0 86 return result;
aoqi@0 87 }
aoqi@0 88 static void set_this(JvmtiGetLoadedClassesClosure* that) {
aoqi@0 89 JavaThread* thread = JavaThread::current();
aoqi@0 90 thread->set_jvmti_get_loaded_classes_closure(that);
aoqi@0 91 }
aoqi@0 92
aoqi@0 93 public:
aoqi@0 94 // Constructor/Destructor
aoqi@0 95 JvmtiGetLoadedClassesClosure() {
aoqi@0 96 JvmtiGetLoadedClassesClosure* that = get_this();
aoqi@0 97 assert(that == NULL, "JvmtiGetLoadedClassesClosure in use");
aoqi@0 98 _initiatingLoader = NULL;
aoqi@0 99 _count = 0;
aoqi@0 100 _list = NULL;
aoqi@0 101 _index = 0;
aoqi@0 102 set_this(this);
aoqi@0 103 }
aoqi@0 104
aoqi@0 105 JvmtiGetLoadedClassesClosure(jobject initiatingLoader) {
aoqi@0 106 JvmtiGetLoadedClassesClosure* that = get_this();
aoqi@0 107 assert(that == NULL, "JvmtiGetLoadedClassesClosure in use");
aoqi@0 108 _initiatingLoader = initiatingLoader;
aoqi@0 109 _count = 0;
aoqi@0 110 _list = NULL;
aoqi@0 111 _index = 0;
aoqi@0 112 set_this(this);
aoqi@0 113 }
aoqi@0 114
aoqi@0 115 ~JvmtiGetLoadedClassesClosure() {
aoqi@0 116 JvmtiGetLoadedClassesClosure* that = get_this();
aoqi@0 117 assert(that != NULL, "JvmtiGetLoadedClassesClosure not found");
aoqi@0 118 set_this(NULL);
aoqi@0 119 _initiatingLoader = NULL;
aoqi@0 120 _count = 0;
aoqi@0 121 if (_list != NULL) {
aoqi@0 122 FreeHeap(_list);
aoqi@0 123 _list = NULL;
aoqi@0 124 }
aoqi@0 125 _index = 0;
aoqi@0 126 }
aoqi@0 127
aoqi@0 128 // Accessors.
aoqi@0 129 jobject get_initiatingLoader() {
aoqi@0 130 return _initiatingLoader;
aoqi@0 131 }
aoqi@0 132
aoqi@0 133 int get_count() {
aoqi@0 134 return _count;
aoqi@0 135 }
aoqi@0 136
aoqi@0 137 void set_count(int value) {
aoqi@0 138 _count = value;
aoqi@0 139 }
aoqi@0 140
aoqi@0 141 Handle* get_list() {
aoqi@0 142 return _list;
aoqi@0 143 }
aoqi@0 144
aoqi@0 145 void set_list(Handle* value) {
aoqi@0 146 _list = value;
aoqi@0 147 }
aoqi@0 148
aoqi@0 149 int get_index() {
aoqi@0 150 return _index;
aoqi@0 151 }
aoqi@0 152
aoqi@0 153 void set_index(int value) {
aoqi@0 154 _index = value;
aoqi@0 155 }
aoqi@0 156
aoqi@0 157 Handle get_element(int index) {
aoqi@0 158 if ((_list != NULL) && (index < _count)) {
aoqi@0 159 return _list[index];
aoqi@0 160 } else {
aoqi@0 161 assert(false, "empty get_element");
aoqi@0 162 return Handle();
aoqi@0 163 }
aoqi@0 164 }
aoqi@0 165
aoqi@0 166 void set_element(int index, Handle value) {
aoqi@0 167 if ((_list != NULL) && (index < _count)) {
aoqi@0 168 _list[index] = value;
aoqi@0 169 } else {
aoqi@0 170 assert(false, "bad set_element");
aoqi@0 171 }
aoqi@0 172 }
aoqi@0 173
aoqi@0 174 // Other predicates
aoqi@0 175 bool available() {
aoqi@0 176 return (_list != NULL);
aoqi@0 177 }
aoqi@0 178
aoqi@0 179 #ifdef ASSERT
aoqi@0 180 // For debugging.
aoqi@0 181 void check(int limit) {
aoqi@0 182 for (int i = 0; i < limit; i += 1) {
aoqi@0 183 assert(Universe::heap()->is_in(get_element(i)()), "check fails");
aoqi@0 184 }
aoqi@0 185 }
aoqi@0 186 #endif
aoqi@0 187
aoqi@0 188 // Public methods that get called within the scope of the closure
aoqi@0 189 void allocate() {
aoqi@0 190 _list = NEW_C_HEAP_ARRAY(Handle, _count, mtInternal);
aoqi@0 191 assert(_list != NULL, "Out of memory");
aoqi@0 192 if (_list == NULL) {
aoqi@0 193 _count = 0;
aoqi@0 194 }
aoqi@0 195 }
aoqi@0 196
aoqi@0 197 void extract(JvmtiEnv *env, jclass* result) {
aoqi@0 198 for (int index = 0; index < _count; index += 1) {
aoqi@0 199 result[index] = (jclass) env->jni_reference(get_element(index));
aoqi@0 200 }
aoqi@0 201 }
aoqi@0 202
aoqi@0 203 static void increment_with_loader(Klass* k, ClassLoaderData* loader_data) {
aoqi@0 204 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
aoqi@0 205 oop class_loader = loader_data->class_loader();
aoqi@0 206 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
aoqi@0 207 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
aoqi@0 208 that->set_count(that->get_count() + 1);
aoqi@0 209 }
aoqi@0 210 }
aoqi@0 211 }
aoqi@0 212
aoqi@0 213 static void prim_array_increment_with_loader(Klass* array, ClassLoaderData* loader_data) {
aoqi@0 214 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
aoqi@0 215 oop class_loader = loader_data->class_loader();
aoqi@0 216 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
aoqi@0 217 that->set_count(that->get_count() + 1);
aoqi@0 218 }
aoqi@0 219 }
aoqi@0 220
aoqi@0 221 static void add_with_loader(Klass* k, ClassLoaderData* loader_data) {
aoqi@0 222 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
aoqi@0 223 if (that->available()) {
aoqi@0 224 oop class_loader = loader_data->class_loader();
aoqi@0 225 if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
aoqi@0 226 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
aoqi@0 227 oop mirror = l->java_mirror();
aoqi@0 228 that->set_element(that->get_index(), mirror);
aoqi@0 229 that->set_index(that->get_index() + 1);
aoqi@0 230 }
aoqi@0 231 }
aoqi@0 232 }
aoqi@0 233 }
aoqi@0 234
aoqi@0 235 // increment the count for the given basic type array class (and any
aoqi@0 236 // multi-dimensional arrays). For example, for [B we check for
aoqi@0 237 // [[B, [[[B, .. and the count is incremented for each one that exists.
aoqi@0 238 static void increment_for_basic_type_arrays(Klass* k) {
aoqi@0 239 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
aoqi@0 240 assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
aoqi@0 241 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
aoqi@0 242 that->set_count(that->get_count() + 1);
aoqi@0 243 }
aoqi@0 244 }
aoqi@0 245
aoqi@0 246 // add the basic type array class and its multi-dimensional array classes to the list
aoqi@0 247 static void add_for_basic_type_arrays(Klass* k) {
aoqi@0 248 JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
aoqi@0 249 assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
aoqi@0 250 assert(that->available(), "no list");
aoqi@0 251 for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
aoqi@0 252 oop mirror = l->java_mirror();
aoqi@0 253 that->set_element(that->get_index(), mirror);
aoqi@0 254 that->set_index(that->get_index() + 1);
aoqi@0 255 }
aoqi@0 256 }
aoqi@0 257 };
aoqi@0 258
aoqi@0 259
aoqi@0 260 jvmtiError
aoqi@0 261 JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {
aoqi@0 262
aoqi@0 263 LoadedClassesClosure closure(env);
aoqi@0 264 {
aoqi@0 265 // To get a consistent list of classes we need MultiArray_lock to ensure
aoqi@0 266 // array classes aren't created.
aoqi@0 267 MutexLocker ma(MultiArray_lock);
aoqi@0 268
aoqi@0 269 // Iterate through all classes in ClassLoaderDataGraph
aoqi@0 270 // and collect them using the LoadedClassesClosure
aoqi@0 271 ClassLoaderDataGraph::loaded_classes_do(&closure);
aoqi@0 272 }
aoqi@0 273
aoqi@0 274 // Return results by extracting the collected contents into a list
aoqi@0 275 // allocated via JvmtiEnv
aoqi@0 276 jclass* result_list;
aoqi@0 277 jvmtiError error = env->Allocate(closure.get_count() * sizeof(jclass),
aoqi@0 278 (unsigned char**)&result_list);
aoqi@0 279
aoqi@0 280 if (error == JVMTI_ERROR_NONE) {
aoqi@0 281 int count = closure.extract(result_list);
aoqi@0 282 *classCountPtr = count;
aoqi@0 283 *classesPtr = result_list;
aoqi@0 284 }
aoqi@0 285 return error;
aoqi@0 286 }
aoqi@0 287
aoqi@0 288 jvmtiError
aoqi@0 289 JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
aoqi@0 290 jint* classCountPtr, jclass** classesPtr) {
aoqi@0 291 // Since SystemDictionary::classes_do only takes a function pointer
aoqi@0 292 // and doesn't call back with a closure data pointer,
aoqi@0 293 // we can only pass static methods.
aoqi@0 294 JvmtiGetLoadedClassesClosure closure(initiatingLoader);
aoqi@0 295 {
aoqi@0 296 // To get a consistent list of classes we need MultiArray_lock to ensure
aoqi@0 297 // array classes aren't created, and SystemDictionary_lock to ensure that
aoqi@0 298 // classes aren't added to the system dictionary,
aoqi@0 299 MutexLocker ma(MultiArray_lock);
aoqi@0 300 MutexLocker sd(SystemDictionary_lock);
aoqi@0 301 // First, count the classes in the system dictionary which have this loader recorded
aoqi@0 302 // as an initiating loader. For basic type arrays this information is not recorded
aoqi@0 303 // so GetClassLoaderClasses will return all of the basic type arrays. This is okay
aoqi@0 304 // because the defining loader for basic type arrays is always the boot class loader
aoqi@0 305 // and these classes are "visible" to all loaders.
aoqi@0 306 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment_with_loader);
aoqi@0 307 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment_for_basic_type_arrays);
aoqi@0 308 // Next, fill in the classes
aoqi@0 309 closure.allocate();
aoqi@0 310 SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add_with_loader);
aoqi@0 311 Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add_for_basic_type_arrays);
aoqi@0 312 // Drop the SystemDictionary_lock, so the results could be wrong from here,
aoqi@0 313 // but we still have a snapshot.
aoqi@0 314 }
aoqi@0 315 // Post results
aoqi@0 316 jclass* result_list;
aoqi@0 317 jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass),
aoqi@0 318 (unsigned char**)&result_list);
aoqi@0 319 if (err != JVMTI_ERROR_NONE) {
aoqi@0 320 return err;
aoqi@0 321 }
aoqi@0 322 closure.extract(env, result_list);
aoqi@0 323 *classCountPtr = closure.get_count();
aoqi@0 324 *classesPtr = result_list;
aoqi@0 325 return JVMTI_ERROR_NONE;
aoqi@0 326 }

mercurial