src/share/vm/prims/jvmtiGetLoadedClasses.cpp

Wed, 08 Oct 2008 08:10:51 -0700

author
ksrini
date
Wed, 08 Oct 2008 08:10:51 -0700
changeset 823
f008d3631bd1
parent 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

6755845: JVM_FindClassFromBoot triggers assertions
Summary: Fixes assertions caused by one jvm_entry calling another, solved by refactoring code and modified gamma test.
Reviewed-by: dholmes, xlu

     1 /*
     2  * Copyright 2003-2005 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    26 # include "incls/_precompiled.incl"
    27 # include "incls/_jvmtiGetLoadedClasses.cpp.incl"
    30 // The closure for GetLoadedClasses and GetClassLoaderClasses
    31 class JvmtiGetLoadedClassesClosure : public StackObj {
    32   // Since the SystemDictionary::classes_do callback
    33   // doesn't pass a closureData pointer,
    34   // we use a thread-local slot to hold a pointer to
    35   // a stack allocated instance of this structure.
    36  private:
    37   jobject _initiatingLoader;
    38   int     _count;
    39   Handle* _list;
    40   int     _index;
    42  private:
    43   // Getting and setting the thread local pointer
    44   static JvmtiGetLoadedClassesClosure* get_this() {
    45     JvmtiGetLoadedClassesClosure* result = NULL;
    46     JavaThread* thread = JavaThread::current();
    47     result = thread->get_jvmti_get_loaded_classes_closure();
    48     return result;
    49   }
    50   static void set_this(JvmtiGetLoadedClassesClosure* that) {
    51     JavaThread* thread = JavaThread::current();
    52     thread->set_jvmti_get_loaded_classes_closure(that);
    53   }
    55  public:
    56   // Constructor/Destructor
    57   JvmtiGetLoadedClassesClosure() {
    58     JvmtiGetLoadedClassesClosure* that = get_this();
    59     assert(that == NULL, "JvmtiGetLoadedClassesClosure in use");
    60     _initiatingLoader = NULL;
    61     _count = 0;
    62     _list = NULL;
    63     _index = 0;
    64     set_this(this);
    65   }
    67   JvmtiGetLoadedClassesClosure(jobject initiatingLoader) {
    68     JvmtiGetLoadedClassesClosure* that = get_this();
    69     assert(that == NULL, "JvmtiGetLoadedClassesClosure in use");
    70     _initiatingLoader = initiatingLoader;
    71     _count = 0;
    72     _list = NULL;
    73     _index = 0;
    74     set_this(this);
    75   }
    77   ~JvmtiGetLoadedClassesClosure() {
    78     JvmtiGetLoadedClassesClosure* that = get_this();
    79     assert(that != NULL, "JvmtiGetLoadedClassesClosure not found");
    80     set_this(NULL);
    81     _initiatingLoader = NULL;
    82     _count = 0;
    83     if (_list != NULL) {
    84       FreeHeap(_list);
    85       _list = NULL;
    86     }
    87     _index = 0;
    88   }
    90   // Accessors.
    91   jobject get_initiatingLoader() {
    92     return _initiatingLoader;
    93   }
    95   int get_count() {
    96     return _count;
    97   }
    99   void set_count(int value) {
   100     _count = value;
   101   }
   103   Handle* get_list() {
   104     return _list;
   105   }
   107   void set_list(Handle* value) {
   108     _list = value;
   109   }
   111   int get_index() {
   112     return _index;
   113   }
   115   void set_index(int value) {
   116     _index = value;
   117   }
   119   Handle get_element(int index) {
   120     if ((_list != NULL) && (index < _count)) {
   121       return _list[index];
   122     } else {
   123       assert(false, "empty get_element");
   124       return Handle();
   125     }
   126   }
   128   void set_element(int index, Handle value) {
   129     if ((_list != NULL) && (index < _count)) {
   130       _list[index] = value;
   131     } else {
   132       assert(false, "bad set_element");
   133     }
   134   }
   136   // Other predicates
   137   bool available() {
   138     return (_list != NULL);
   139   }
   141 #ifdef ASSERT
   142   // For debugging.
   143   void check(int limit) {
   144     for (int i = 0; i < limit; i += 1) {
   145       assert(Universe::heap()->is_in(get_element(i)()), "check fails");
   146     }
   147   }
   148 #endif
   150   // Public methods that get called within the scope of the closure
   151   void allocate() {
   152     _list = NEW_C_HEAP_ARRAY(Handle, _count);
   153     assert(_list != NULL, "Out of memory");
   154     if (_list == NULL) {
   155       _count = 0;
   156     }
   157   }
   159   void extract(JvmtiEnv *env, jclass* result) {
   160     for (int index = 0; index < _count; index += 1) {
   161       result[index] = (jclass) env->jni_reference(get_element(index));
   162     }
   163   }
   165   // Finally, the static methods that are the callbacks
   166   static void increment(klassOop k) {
   167     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   168     if (that->get_initiatingLoader() == NULL) {
   169       for (klassOop l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) {
   170         that->set_count(that->get_count() + 1);
   171       }
   172     } else if (k != NULL) {
   173       // if initiating loader not null, just include the instance with 1 dimension
   174       that->set_count(that->get_count() + 1);
   175     }
   176   }
   178   static void increment_with_loader(klassOop k, oop loader) {
   179     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   180     if (loader == JNIHandles::resolve(that->get_initiatingLoader())) {
   181       for (klassOop l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) {
   182         that->set_count(that->get_count() + 1);
   183       }
   184     }
   185   }
   187   static void prim_array_increment_with_loader(klassOop array, oop loader) {
   188     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   189     if (loader == JNIHandles::resolve(that->get_initiatingLoader())) {
   190       that->set_count(that->get_count() + 1);
   191     }
   192   }
   194   static void add(klassOop k) {
   195     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   196     if (that->available()) {
   197       if (that->get_initiatingLoader() == NULL) {
   198         for (klassOop l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) {
   199           oop mirror = Klass::cast(l)->java_mirror();
   200           that->set_element(that->get_index(), mirror);
   201           that->set_index(that->get_index() + 1);
   202         }
   203       } else if (k != NULL) {
   204         // if initiating loader not null, just include the instance with 1 dimension
   205         oop mirror = Klass::cast(k)->java_mirror();
   206         that->set_element(that->get_index(), mirror);
   207         that->set_index(that->get_index() + 1);
   208       }
   209     }
   210   }
   212   static void add_with_loader(klassOop k, oop loader) {
   213     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   214     if (that->available()) {
   215       if (loader == JNIHandles::resolve(that->get_initiatingLoader())) {
   216         for (klassOop l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) {
   217           oop mirror = Klass::cast(l)->java_mirror();
   218           that->set_element(that->get_index(), mirror);
   219           that->set_index(that->get_index() + 1);
   220         }
   221       }
   222     }
   223   }
   225   // increment the count for the given basic type array class (and any
   226   // multi-dimensional arrays). For example, for [B we check for
   227   // [[B, [[[B, .. and the count is incremented for each one that exists.
   228   static void increment_for_basic_type_arrays(klassOop k) {
   229     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   230     assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
   231     for (klassOop l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) {
   232       that->set_count(that->get_count() + 1);
   233     }
   234   }
   236   // add the basic type array class and its multi-dimensional array classes to the list
   237   static void add_for_basic_type_arrays(klassOop k) {
   238     JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
   239     assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
   240     assert(that->available(), "no list");
   241     for (klassOop l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) {
   242       oop mirror = Klass::cast(l)->java_mirror();
   243       that->set_element(that->get_index(), mirror);
   244       that->set_index(that->get_index() + 1);
   245     }
   246   }
   247 };
   250 jvmtiError
   251 JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {
   252   // Since SystemDictionary::classes_do only takes a function pointer
   253   // and doesn't call back with a closure data pointer,
   254   // we can only pass static methods.
   256   JvmtiGetLoadedClassesClosure closure;
   257   {
   258     // To get a consistent list of classes we need MultiArray_lock to ensure
   259     // array classes aren't created, and SystemDictionary_lock to ensure that
   260     // classes aren't added to the system dictionary,
   261     MutexLocker ma(MultiArray_lock);
   262     MutexLocker sd(SystemDictionary_lock);
   264     // First, count the classes
   265     SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment);
   266     Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment);
   267     // Next, fill in the classes
   268     closure.allocate();
   269     SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add);
   270     Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add);
   271     // Drop the SystemDictionary_lock, so the results could be wrong from here,
   272     // but we still have a snapshot.
   273   }
   274   // Post results
   275   jclass* result_list;
   276   jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass),
   277                                  (unsigned char**)&result_list);
   278   if (err != JVMTI_ERROR_NONE) {
   279     return err;
   280   }
   281   closure.extract(env, result_list);
   282   *classCountPtr = closure.get_count();
   283   *classesPtr = result_list;
   284   return JVMTI_ERROR_NONE;
   285 }
   287 jvmtiError
   288 JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
   289                                              jint* classCountPtr, jclass** classesPtr) {
   290   // Since SystemDictionary::classes_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 system dictionary,
   298     MutexLocker ma(MultiArray_lock);
   299     MutexLocker sd(SystemDictionary_lock);
   300     // First, count the classes in the system dictionary 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     SystemDictionary::classes_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     SystemDictionary::classes_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 }

mercurial