src/share/vm/prims/jvmtiGetLoadedClasses.cpp

Wed, 27 Aug 2014 08:19:12 -0400

author
zgu
date
Wed, 27 Aug 2014 08:19:12 -0400
changeset 7074
833b0f92429a
parent 6198
55fb97c4c58d
child 6876
710a3c8b516e
child 9195
9ffa7549c389
permissions
-rw-r--r--

8046598: Scalable Native memory tracking development
Summary: Enhance scalability of native memory tracking
Reviewed-by: coleenp, ctornqvi, gtriantafill

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

mercurial