jdk/src/demo/share/jvmti/hprof/hprof_class.c
changeset 25859 3317bb8137f4
parent 23010 6dadb192ad81
equal deleted inserted replaced
25858:836adbf7a2cd 25859:3317bb8137f4
       
     1 /*
       
     2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  *
       
     8  *   - Redistributions of source code must retain the above copyright
       
     9  *     notice, this list of conditions and the following disclaimer.
       
    10  *
       
    11  *   - Redistributions in binary form must reproduce the above copyright
       
    12  *     notice, this list of conditions and the following disclaimer in the
       
    13  *     documentation and/or other materials provided with the distribution.
       
    14  *
       
    15  *   - Neither the name of Oracle nor the names of its
       
    16  *     contributors may be used to endorse or promote products derived
       
    17  *     from this software without specific prior written permission.
       
    18  *
       
    19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
       
    20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
       
    21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
       
    23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
       
    27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
       
    28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
       
    29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    30  */
       
    31 
       
    32 /*
       
    33  * This source code is provided to illustrate the usage of a given feature
       
    34  * or technique and has been deliberately simplified. Additional steps
       
    35  * required for a production-quality application, such as security checks,
       
    36  * input validation and proper error handling, might not be present in
       
    37  * this sample code.
       
    38  */
       
    39 
       
    40 
       
    41 /* Table of class information.
       
    42  *
       
    43  *   Each element in this table is identified with a ClassIndex.
       
    44  *   Each element is uniquely identified by it's signature and loader.
       
    45  *   Every class load has a unique class serial number.
       
    46  *   While loaded, each element will have a cache of a global reference
       
    47  *     to it's jclass object, plus jmethodID's as needed.
       
    48  *   Method signatures and names are obtained via BCI.
       
    49  *   Methods can be identified with a ClassIndex and MethodIndex pair,
       
    50  *     where the MethodIndex matches the index of the method name and
       
    51  *     signature arrays obtained from the BCI pass.
       
    52  *   Strings are stored in the string table and a StringIndex is used.
       
    53  *   Class Loaders are stored in the loader table and a LoaderIndex is used.
       
    54  *   Since the jclass object is an object, at some point an object table
       
    55  *      entry may be allocated for the jclass as an ObjectIndex.
       
    56  */
       
    57 
       
    58 #include "hprof.h"
       
    59 
       
    60 /* Effectively represents a jclass object. */
       
    61 
       
    62 /* These table elements are made unique by and sorted by signature name. */
       
    63 
       
    64 typedef struct ClassKey {
       
    65     StringIndex    sig_string_index;    /* Signature of class */
       
    66     LoaderIndex    loader_index;        /* Index for class loader */
       
    67 } ClassKey;
       
    68 
       
    69 /* Each class could contain method information, gotten from BCI callback */
       
    70 
       
    71 typedef struct MethodInfo {
       
    72     StringIndex  name_index;    /* Method name, index into string table */
       
    73     StringIndex  sig_index;     /* Method signature, index into string table */
       
    74     jmethodID    method_id;     /* Method ID, possibly NULL at first */
       
    75 } MethodInfo;
       
    76 
       
    77 /* The basic class information we save */
       
    78 
       
    79 typedef struct ClassInfo {
       
    80     jclass         classref;            /* Global ref to jclass */
       
    81     MethodInfo    *method;              /* Array of method data */
       
    82     int            method_count;        /* Count of methods */
       
    83     ObjectIndex    object_index;        /* Optional object index for jclass */
       
    84     SerialNumber   serial_num;          /* Unique to the actual class load */
       
    85     ClassStatus    status;              /* Current class status (bit mask) */
       
    86     ClassIndex     super;               /* Super class in this table */
       
    87     StringIndex    name;                /* Name of class */
       
    88     jint           inst_size;           /* #bytes needed for instance fields */
       
    89     jint           field_count;         /* Number of all fields */
       
    90     FieldInfo     *field;               /* Pointer to all FieldInfo's */
       
    91 } ClassInfo;
       
    92 
       
    93 /* Private interfaces */
       
    94 
       
    95 static ClassKey*
       
    96 get_pkey(ClassIndex index)
       
    97 {
       
    98     void *key_ptr;
       
    99     int   key_len;
       
   100 
       
   101     table_get_key(gdata->class_table, index, (void*)&key_ptr, &key_len);
       
   102     HPROF_ASSERT(key_len==sizeof(ClassKey));
       
   103     HPROF_ASSERT(key_ptr!=NULL);
       
   104     return (ClassKey*)key_ptr;
       
   105 }
       
   106 
       
   107 static void
       
   108 fillin_pkey(const char *sig, LoaderIndex loader_index, ClassKey *pkey)
       
   109 {
       
   110     static ClassKey empty_key;
       
   111 
       
   112     HPROF_ASSERT(loader_index!=0);
       
   113     *pkey                  = empty_key;
       
   114     pkey->sig_string_index = string_find_or_create(sig);
       
   115     pkey->loader_index     = loader_index;
       
   116 }
       
   117 
       
   118 static ClassInfo *
       
   119 get_info(ClassIndex index)
       
   120 {
       
   121     ClassInfo *info;
       
   122 
       
   123     info = (ClassInfo*)table_get_info(gdata->class_table, index);
       
   124     return info;
       
   125 }
       
   126 
       
   127 static void
       
   128 fill_info(TableIndex index, ClassKey *pkey)
       
   129 {
       
   130     ClassInfo *info;
       
   131     char      *sig;
       
   132 
       
   133     info = get_info(index);
       
   134     info->serial_num = gdata->class_serial_number_counter++;
       
   135     info->method_count = 0;
       
   136     info->inst_size = -1;
       
   137     info->field_count = -1;
       
   138     info->field = NULL;
       
   139     sig = string_get(pkey->sig_string_index);
       
   140     if ( sig[0] != JVM_SIGNATURE_CLASS ) {
       
   141         info->name = pkey->sig_string_index;
       
   142     } else {
       
   143         int        len;
       
   144 
       
   145         len = string_get_len(pkey->sig_string_index);
       
   146         if ( len > 2  ) {
       
   147             char      *name;
       
   148 
       
   149             /* Class signature looks like "Lname;", we want "name" here. */
       
   150             name = HPROF_MALLOC(len-1);
       
   151             (void)memcpy(name, sig+1, len-2);
       
   152             name[len-2] = 0;
       
   153             info->name = string_find_or_create(name);
       
   154             HPROF_FREE(name);
       
   155         } else {
       
   156             /* This would be strange, a class signature not in "Lname;" form? */
       
   157             info->name = pkey->sig_string_index;
       
   158         }
       
   159    }
       
   160 }
       
   161 
       
   162 static ClassIndex
       
   163 find_entry(ClassKey *pkey)
       
   164 {
       
   165     ClassIndex index;
       
   166 
       
   167     index = table_find_entry(gdata->class_table,
       
   168                                 (void*)pkey, (int)sizeof(ClassKey));
       
   169     return index;
       
   170 }
       
   171 
       
   172 static ClassIndex
       
   173 create_entry(ClassKey *pkey)
       
   174 {
       
   175     ClassIndex index;
       
   176 
       
   177     index = table_create_entry(gdata->class_table,
       
   178                                 (void*)pkey, (int)sizeof(ClassKey), NULL);
       
   179     fill_info(index, pkey);
       
   180     return index;
       
   181 }
       
   182 
       
   183 static ClassIndex
       
   184 find_or_create_entry(ClassKey *pkey)
       
   185 {
       
   186     ClassIndex      index;
       
   187 
       
   188     HPROF_ASSERT(pkey!=NULL);
       
   189     HPROF_ASSERT(pkey->loader_index!=0);
       
   190     index = find_entry(pkey);
       
   191     if ( index == 0 ) {
       
   192         index = create_entry(pkey);
       
   193     }
       
   194     return index;
       
   195 }
       
   196 
       
   197 static void
       
   198 delete_classref(JNIEnv *env, ClassInfo *info, jclass klass)
       
   199 {
       
   200     jclass ref;
       
   201     int    i;
       
   202 
       
   203     HPROF_ASSERT(env!=NULL);
       
   204     HPROF_ASSERT(info!=NULL);
       
   205 
       
   206     for ( i = 0 ; i < info->method_count ; i++ ) {
       
   207         info->method[i].method_id  = NULL;
       
   208     }
       
   209     ref = info->classref;
       
   210     if ( klass != NULL ) {
       
   211         info->classref = newGlobalReference(env, klass);
       
   212     } else {
       
   213         info->classref = NULL;
       
   214     }
       
   215     if ( ref != NULL ) {
       
   216         deleteGlobalReference(env, ref);
       
   217     }
       
   218 }
       
   219 
       
   220 static void
       
   221 cleanup_item(TableIndex index, void *key_ptr, int key_len,
       
   222                                 void *info_ptr, void *arg)
       
   223 {
       
   224     ClassInfo *info;
       
   225 
       
   226     /* Cleanup any information in this ClassInfo structure. */
       
   227     HPROF_ASSERT(key_ptr!=NULL);
       
   228     HPROF_ASSERT(key_len==sizeof(ClassKey));
       
   229     HPROF_ASSERT(info_ptr!=NULL);
       
   230     info = (ClassInfo *)info_ptr;
       
   231     if ( info->method_count > 0 ) {
       
   232         HPROF_FREE((void*)info->method);
       
   233         info->method_count = 0;
       
   234         info->method       = NULL;
       
   235     }
       
   236     if ( info->field != NULL ) {
       
   237         HPROF_FREE((void*)info->field);
       
   238         info->field_count = 0;
       
   239         info->field      = NULL;
       
   240     }
       
   241 }
       
   242 
       
   243 static void
       
   244 delete_ref_item(TableIndex index, void *key_ptr, int key_len,
       
   245                                 void *info_ptr, void *arg)
       
   246 {
       
   247     delete_classref((JNIEnv*)arg, (ClassInfo*)info_ptr, NULL);
       
   248 }
       
   249 
       
   250 static void
       
   251 list_item(TableIndex index, void *key_ptr, int key_len,
       
   252                                 void *info_ptr, void *arg)
       
   253 {
       
   254     ClassInfo *info;
       
   255     ClassKey   key;
       
   256     char      *sig;
       
   257     int        i;
       
   258 
       
   259     HPROF_ASSERT(key_ptr!=NULL);
       
   260     HPROF_ASSERT(key_len==sizeof(ClassKey));
       
   261     HPROF_ASSERT(info_ptr!=NULL);
       
   262     key = *((ClassKey*)key_ptr);
       
   263     sig = string_get(key.sig_string_index);
       
   264     info = (ClassInfo *)info_ptr;
       
   265     debug_message(
       
   266              "0x%08x: Class %s, SN=%u, status=0x%08x, ref=%p,"
       
   267              " method_count=%d\n",
       
   268              index,
       
   269              (const char *)sig,
       
   270              info->serial_num,
       
   271              info->status,
       
   272              (void*)info->classref,
       
   273              info->method_count);
       
   274     if ( info->method_count > 0 ) {
       
   275         for ( i = 0 ; i < info->method_count ; i++ ) {
       
   276             debug_message(
       
   277                 "    Method %d: \"%s\", sig=\"%s\", method=%p\n",
       
   278                 i,
       
   279                 string_get(info->method[i].name_index),
       
   280                 string_get(info->method[i].sig_index),
       
   281                 (void*)info->method[i].method_id);
       
   282         }
       
   283     }
       
   284 }
       
   285 
       
   286 static void
       
   287 all_status_remove(TableIndex index, void *key_ptr, int key_len,
       
   288                                 void *info_ptr, void *arg)
       
   289 {
       
   290     ClassInfo   *info;
       
   291     ClassStatus  status;
       
   292 
       
   293     HPROF_ASSERT(info_ptr!=NULL);
       
   294     /*LINTED*/
       
   295     status = (ClassStatus)(long)(ptrdiff_t)arg;
       
   296     info = (ClassInfo *)info_ptr;
       
   297     info->status &= (~status);
       
   298 }
       
   299 
       
   300 static void
       
   301 unload_walker(TableIndex index, void *key_ptr, int key_len,
       
   302                                 void *info_ptr, void *arg)
       
   303 {
       
   304     ClassInfo        *info;
       
   305 
       
   306     HPROF_ASSERT(info_ptr!=NULL);
       
   307     info = (ClassInfo *)info_ptr;
       
   308     if ( ! ( info->status & CLASS_IN_LOAD_LIST ) ) {
       
   309         if ( ! (info->status & (CLASS_SPECIAL|CLASS_SYSTEM|CLASS_UNLOADED)) ) {
       
   310             io_write_class_unload(info->serial_num, info->object_index);
       
   311             info->status |= CLASS_UNLOADED;
       
   312             delete_classref((JNIEnv*)arg, info, NULL);
       
   313         }
       
   314     }
       
   315 }
       
   316 
       
   317 /* External interfaces */
       
   318 
       
   319 void
       
   320 class_init(void)
       
   321 {
       
   322     HPROF_ASSERT(gdata->class_table==NULL);
       
   323     gdata->class_table = table_initialize("Class", 512, 512, 511,
       
   324                                     (int)sizeof(ClassInfo));
       
   325 }
       
   326 
       
   327 ClassIndex
       
   328 class_find_or_create(const char *sig, LoaderIndex loader_index)
       
   329 {
       
   330     ClassKey key;
       
   331 
       
   332     fillin_pkey(sig, loader_index, &key);
       
   333     return find_or_create_entry(&key);
       
   334 }
       
   335 
       
   336 ClassIndex
       
   337 class_create(const char *sig, LoaderIndex loader_index)
       
   338 {
       
   339     ClassKey key;
       
   340 
       
   341     fillin_pkey(sig, loader_index, &key);
       
   342     return create_entry(&key);
       
   343 }
       
   344 
       
   345 void
       
   346 class_prime_system_classes(void)
       
   347 {
       
   348     /* Prime System classes? Anything before VM_START is System class.
       
   349      *   Or classes loaded before env arg is non-NULL.
       
   350      *   Or any of the classes listed below.
       
   351      */
       
   352     static const char * signatures[] =
       
   353         {
       
   354             "Ljava/lang/Object;",
       
   355             "Ljava/io/Serializable;",
       
   356             "Ljava/lang/String;",
       
   357             "Ljava/lang/Class;",
       
   358             "Ljava/lang/ClassLoader;",
       
   359             "Ljava/lang/System;",
       
   360             "Ljava/lang/Thread;",
       
   361             "Ljava/lang/ThreadGroup;",
       
   362         };
       
   363     int n_signatures;
       
   364     int i;
       
   365     LoaderIndex loader_index;
       
   366 
       
   367     n_signatures = (int)sizeof(signatures)/(int)sizeof(signatures[0]);
       
   368     loader_index = loader_find_or_create(NULL, NULL);
       
   369     for ( i = 0 ; i < n_signatures ; i++ ) {
       
   370         ClassInfo  *info;
       
   371         ClassIndex  index;
       
   372         ClassKey    key;
       
   373 
       
   374         fillin_pkey(signatures[i], loader_index, &key);
       
   375         index = find_or_create_entry(&key);
       
   376         info = get_info(index);
       
   377         info->status |= CLASS_SYSTEM;
       
   378     }
       
   379 }
       
   380 
       
   381 void
       
   382 class_add_status(ClassIndex index, ClassStatus status)
       
   383 {
       
   384     ClassInfo *info;
       
   385 
       
   386     info = get_info(index);
       
   387     info->status |= status;
       
   388 }
       
   389 
       
   390 ClassStatus
       
   391 class_get_status(ClassIndex index)
       
   392 {
       
   393     ClassInfo *info;
       
   394 
       
   395     info = get_info(index);
       
   396     return info->status;
       
   397 }
       
   398 
       
   399 StringIndex
       
   400 class_get_signature(ClassIndex index)
       
   401 {
       
   402     ClassKey *pkey;
       
   403 
       
   404     pkey = get_pkey(index);
       
   405     return pkey->sig_string_index;
       
   406 }
       
   407 
       
   408 SerialNumber
       
   409 class_get_serial_number(ClassIndex index)
       
   410 {
       
   411     ClassInfo *info;
       
   412 
       
   413     if ( index == 0 ) {
       
   414         return 0;
       
   415     }
       
   416     info = get_info(index);
       
   417     return info->serial_num;
       
   418 }
       
   419 
       
   420 void
       
   421 class_all_status_remove(ClassStatus status)
       
   422 {
       
   423     table_walk_items(gdata->class_table, &all_status_remove,
       
   424                 (void*)(ptrdiff_t)(long)status);
       
   425 }
       
   426 
       
   427 void
       
   428 class_do_unloads(JNIEnv *env)
       
   429 {
       
   430     table_walk_items(gdata->class_table, &unload_walker, (void*)env);
       
   431 }
       
   432 
       
   433 void
       
   434 class_list(void)
       
   435 {
       
   436     debug_message(
       
   437         "--------------------- Class Table ------------------------\n");
       
   438     table_walk_items(gdata->class_table, &list_item, NULL);
       
   439     debug_message(
       
   440         "----------------------------------------------------------\n");
       
   441 }
       
   442 
       
   443 void
       
   444 class_cleanup(void)
       
   445 {
       
   446     table_cleanup(gdata->class_table, &cleanup_item, NULL);
       
   447     gdata->class_table = NULL;
       
   448 }
       
   449 
       
   450 void
       
   451 class_delete_global_references(JNIEnv* env)
       
   452 {
       
   453     table_walk_items(gdata->class_table, &delete_ref_item, (void*)env);
       
   454 }
       
   455 
       
   456 void
       
   457 class_set_methods(ClassIndex index, const char **name, const char **sig,
       
   458                         int count)
       
   459 {
       
   460     ClassInfo *info;
       
   461     int        i;
       
   462 
       
   463     info               = get_info(index);
       
   464     if ( info->method_count > 0 ) {
       
   465         HPROF_FREE((void*)info->method);
       
   466         info->method_count = 0;
       
   467         info->method       = NULL;
       
   468     }
       
   469     info->method_count = count;
       
   470     if ( count > 0 ) {
       
   471         info->method = (MethodInfo *)HPROF_MALLOC(count*(int)sizeof(MethodInfo));
       
   472         for ( i = 0 ; i < count ; i++ ) {
       
   473             info->method[i].name_index = string_find_or_create(name[i]);
       
   474             info->method[i].sig_index  = string_find_or_create(sig[i]);
       
   475             info->method[i].method_id  = NULL;
       
   476         }
       
   477     }
       
   478 }
       
   479 
       
   480 jclass
       
   481 class_new_classref(JNIEnv *env, ClassIndex index, jclass classref)
       
   482 {
       
   483     ClassInfo *info;
       
   484 
       
   485     HPROF_ASSERT(classref!=NULL);
       
   486     info = get_info(index);
       
   487     if ( ! isSameObject(env, classref, info->classref) ) {
       
   488         delete_classref(env, info, classref);
       
   489     }
       
   490     return info->classref;
       
   491 }
       
   492 
       
   493 jclass
       
   494 class_get_class(JNIEnv *env, ClassIndex index)
       
   495 {
       
   496     ClassInfo *info;
       
   497     jclass     clazz;
       
   498 
       
   499     info        = get_info(index);
       
   500     clazz       = info->classref;
       
   501     if ( env != NULL && clazz == NULL ) {
       
   502         WITH_LOCAL_REFS(env, 1) {
       
   503             jclass   new_clazz;
       
   504             char    *class_name;
       
   505 
       
   506             class_name = string_get(info->name);
       
   507             /* This really only makes sense for the bootclass classes,
       
   508              *   since FindClass doesn't provide a way to load a class in
       
   509              *   a specific class loader.
       
   510              */
       
   511             new_clazz = findClass(env, class_name);
       
   512             if ( new_clazz == NULL ) {
       
   513                 HPROF_ERROR(JNI_TRUE, "Cannot load class with findClass");
       
   514             }
       
   515             HPROF_ASSERT(new_clazz!=NULL);
       
   516             clazz = class_new_classref(env, index, new_clazz);
       
   517         } END_WITH_LOCAL_REFS;
       
   518         HPROF_ASSERT(clazz!=NULL);
       
   519     }
       
   520     return clazz;
       
   521 }
       
   522 
       
   523 jmethodID
       
   524 class_get_methodID(JNIEnv *env, ClassIndex index, MethodIndex mnum)
       
   525 {
       
   526     ClassInfo *info;
       
   527     jmethodID  method;
       
   528 
       
   529     info = get_info(index);
       
   530     if (mnum >= info->method_count) {
       
   531         jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
       
   532         (*env)->ThrowNew(env, newExcCls, "Illegal mnum");
       
   533 
       
   534         return NULL;
       
   535     }
       
   536     method = info->method[mnum].method_id;
       
   537     if ( method == NULL ) {
       
   538         char * name;
       
   539         char * sig;
       
   540         jclass clazz;
       
   541 
       
   542         name  = (char *)string_get(info->method[mnum].name_index);
       
   543         if (name==NULL) {
       
   544             jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
       
   545             (*env)->ThrowNew(env, newExcCls, "Name not found");
       
   546 
       
   547             return NULL;
       
   548         }
       
   549         sig   = (char *)string_get(info->method[mnum].sig_index);
       
   550         HPROF_ASSERT(sig!=NULL);
       
   551         clazz = class_get_class(env, index);
       
   552         if ( clazz != NULL ) {
       
   553             method = getMethodID(env, clazz, name, sig);
       
   554             HPROF_ASSERT(method!=NULL);
       
   555             info = get_info(index);
       
   556             info->method[mnum].method_id = method;
       
   557         }
       
   558     }
       
   559     return method;
       
   560 }
       
   561 
       
   562 void
       
   563 class_set_inst_size(ClassIndex index, jint inst_size)
       
   564 {
       
   565     ClassInfo *info;
       
   566 
       
   567     info = get_info(index);
       
   568     info->inst_size = inst_size;
       
   569 }
       
   570 
       
   571 jint
       
   572 class_get_inst_size(ClassIndex index)
       
   573 {
       
   574     ClassInfo *info;
       
   575 
       
   576     info = get_info(index);
       
   577     return info->inst_size;
       
   578 }
       
   579 
       
   580 void
       
   581 class_set_object_index(ClassIndex index, ObjectIndex object_index)
       
   582 {
       
   583     ClassInfo *info;
       
   584 
       
   585     info = get_info(index);
       
   586     info->object_index = object_index;
       
   587 }
       
   588 
       
   589 ObjectIndex
       
   590 class_get_object_index(ClassIndex index)
       
   591 {
       
   592     ClassInfo *info;
       
   593 
       
   594     info = get_info(index);
       
   595     return info->object_index;
       
   596 }
       
   597 
       
   598 ClassIndex
       
   599 class_get_super(ClassIndex index)
       
   600 {
       
   601     ClassInfo *info;
       
   602 
       
   603     info = get_info(index);
       
   604     return info->super;
       
   605 }
       
   606 
       
   607 void
       
   608 class_set_super(ClassIndex index, ClassIndex super)
       
   609 {
       
   610     ClassInfo *info;
       
   611 
       
   612     info = get_info(index);
       
   613     info->super = super;
       
   614 }
       
   615 
       
   616 LoaderIndex
       
   617 class_get_loader(ClassIndex index)
       
   618 {
       
   619     ClassKey *pkey;
       
   620 
       
   621     pkey = get_pkey(index);
       
   622     HPROF_ASSERT(pkey->loader_index!=0);
       
   623     return pkey->loader_index;
       
   624 }
       
   625 
       
   626 /* Get ALL class fields (supers too), return 1 on error, 0 if ok */
       
   627 jint
       
   628 class_get_all_fields(JNIEnv *env, ClassIndex index,
       
   629                 jint *pfield_count, FieldInfo **pfield)
       
   630 {
       
   631     ClassInfo  *info;
       
   632     FieldInfo  *finfo;
       
   633     jint        count;
       
   634     jint        ret;
       
   635 
       
   636     count = 0;
       
   637     finfo = NULL;
       
   638     ret   = 1;       /* Default is to return an error condition */
       
   639 
       
   640     info = get_info(index);
       
   641     if ( info != NULL ) {
       
   642         if ( info->field_count >= 0 ) {
       
   643             /* Get cache */
       
   644             count = info->field_count;
       
   645             finfo = info->field;
       
   646             ret   = 0;                 /* Return of cache data, no error */
       
   647         } else {
       
   648             jclass     klass;
       
   649 
       
   650             klass = info->classref;
       
   651             if ( klass == NULL || isSameObject(env, klass, NULL) ) {
       
   652                 /* This is probably an error because this will cause the field
       
   653                  *    index values to be off, but I'm hesitant to generate a
       
   654                  *    fatal error here, so I will issue something and continue.
       
   655                  *    I should have been holding a global reference to all the
       
   656                  *    jclass, so I'm not sure how this could happen.
       
   657                  *    Issuing a FindClass() here is just asking for trouble
       
   658                  *    because if the class went away, we aren't even sure
       
   659                  *    what ClassLoader to use.
       
   660                  */
       
   661                 HPROF_ERROR(JNI_FALSE, "Missing jclass when fields needed");
       
   662             } else {
       
   663                 jint status;
       
   664 
       
   665                 status = getClassStatus(klass);
       
   666                 if ( status &
       
   667                     (JVMTI_CLASS_STATUS_PRIMITIVE|JVMTI_CLASS_STATUS_ARRAY) ) {
       
   668                     /* Set cache */
       
   669                     info->field_count = count;
       
   670                     info->field       = finfo;
       
   671                     ret               = 0;      /* Primitive or array ok */
       
   672                 } else if ( status & JVMTI_CLASS_STATUS_PREPARED ) {
       
   673                     /* Call JVMTI to get them */
       
   674                     getAllClassFieldInfo(env, klass, &count, &finfo);
       
   675                     /* Set cache */
       
   676                     info->field_count = count;
       
   677                     info->field       = finfo;
       
   678                     ret               = 0;
       
   679                 }
       
   680             }
       
   681         }
       
   682     }
       
   683     *pfield_count = count;
       
   684     *pfield       = finfo;
       
   685     return ret;
       
   686 }