jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.c
changeset 32234 421773f441c6
parent 32208 13203adcd002
parent 32233 d97dc26de1d7
child 32235 26648f472fe5
equal deleted inserted replaced
32208:13203adcd002 32234:421773f441c6
     1 /*
       
     2  * Copyright (c) 2003, 2011, 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 /* The Class Loader table. */
       
    42 
       
    43 /*
       
    44  * The Class Loader objects show up so early in the VM process that a
       
    45  *   separate table was designated for Class Loaders.
       
    46  *
       
    47  * The Class Loader is unique by way of it's jobject uniqueness, unfortunately
       
    48  *   use of JNI too early for jobject comparisons is problematic.
       
    49  *   It is assumed that the number of class loaders will be limited, and
       
    50  *   a simple linear search will be performed for now.
       
    51  *   That logic is isolated here and can be changed to use the standard
       
    52  *   table hash table search once we know JNI can be called safely.
       
    53  *
       
    54  * A weak global reference is created to keep tabs on loaders, and as
       
    55  *   each search for a loader happens, NULL weak global references will
       
    56  *   trigger the freedom of those entries.
       
    57  *
       
    58  */
       
    59 
       
    60 #include "hprof.h"
       
    61 
       
    62 typedef struct {
       
    63     jobject         globalref;    /* Weak Global reference for object */
       
    64     ObjectIndex     object_index;
       
    65 } LoaderInfo;
       
    66 
       
    67 static LoaderInfo *
       
    68 get_info(LoaderIndex index)
       
    69 {
       
    70     return (LoaderInfo*)table_get_info(gdata->loader_table, index);
       
    71 }
       
    72 
       
    73 static void
       
    74 delete_globalref(JNIEnv *env, LoaderInfo *info)
       
    75 {
       
    76     jobject     ref;
       
    77 
       
    78     HPROF_ASSERT(env!=NULL);
       
    79     HPROF_ASSERT(info!=NULL);
       
    80     ref = info->globalref;
       
    81     info->globalref = NULL;
       
    82     if ( ref != NULL ) {
       
    83         deleteWeakGlobalReference(env, ref);
       
    84     }
       
    85     info->object_index = 0;
       
    86 }
       
    87 
       
    88 static void
       
    89 cleanup_item(TableIndex index, void *key_ptr, int key_len,
       
    90                         void *info_ptr, void *arg)
       
    91 {
       
    92 }
       
    93 
       
    94 static void
       
    95 delete_ref_item(TableIndex index, void *key_ptr, int key_len,
       
    96                         void *info_ptr, void *arg)
       
    97 {
       
    98     delete_globalref((JNIEnv*)arg, (LoaderInfo*)info_ptr);
       
    99 }
       
   100 
       
   101 static void
       
   102 list_item(TableIndex index, void *key_ptr, int key_len,
       
   103                         void *info_ptr, void *arg)
       
   104 {
       
   105     LoaderInfo     *info;
       
   106 
       
   107     HPROF_ASSERT(info_ptr!=NULL);
       
   108 
       
   109     info        = (LoaderInfo*)info_ptr;
       
   110     debug_message( "Loader 0x%08x: globalref=%p, object_index=%d\n",
       
   111                 index, (void*)info->globalref, info->object_index);
       
   112 }
       
   113 
       
   114 static void
       
   115 free_entry(JNIEnv *env, LoaderIndex index)
       
   116 {
       
   117     LoaderInfo *info;
       
   118 
       
   119     info = get_info(index);
       
   120     delete_globalref(env, info);
       
   121     table_free_entry(gdata->loader_table, index);
       
   122 }
       
   123 
       
   124 typedef struct SearchData {
       
   125     JNIEnv *env;
       
   126     jobject loader;
       
   127     LoaderIndex found;
       
   128 } SearchData;
       
   129 
       
   130 static void
       
   131 search_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
       
   132 {
       
   133     LoaderInfo  *info;
       
   134     SearchData  *data;
       
   135 
       
   136     HPROF_ASSERT(info_ptr!=NULL);
       
   137     HPROF_ASSERT(arg!=NULL);
       
   138     info        = (LoaderInfo*)info_ptr;
       
   139     data        = (SearchData*)arg;
       
   140     if ( data->loader == info->globalref ) {
       
   141         /* Covers when looking for NULL too. */
       
   142         HPROF_ASSERT(data->found==0); /* Did we find more than one? */
       
   143         data->found = index;
       
   144     } else if ( data->env != NULL && data->loader != NULL &&
       
   145                 info->globalref != NULL ) {
       
   146         jobject lref;
       
   147 
       
   148         lref = newLocalReference(data->env, info->globalref);
       
   149         if ( lref == NULL ) {
       
   150             /* Object went away, free reference and entry */
       
   151             free_entry(data->env, index);
       
   152         } else if ( isSameObject(data->env, data->loader, lref) ) {
       
   153             HPROF_ASSERT(data->found==0); /* Did we find more than one? */
       
   154             data->found = index;
       
   155         }
       
   156         if ( lref != NULL ) {
       
   157             deleteLocalReference(data->env, lref);
       
   158         }
       
   159     }
       
   160 
       
   161 }
       
   162 
       
   163 static LoaderIndex
       
   164 search(JNIEnv *env, jobject loader)
       
   165 {
       
   166     SearchData  data;
       
   167 
       
   168     data.env    = env;
       
   169     data.loader = loader;
       
   170     data.found  = 0;
       
   171     table_walk_items(gdata->loader_table, &search_item, (void*)&data);
       
   172     return data.found;
       
   173 }
       
   174 
       
   175 LoaderIndex
       
   176 loader_find_or_create(JNIEnv *env, jobject loader)
       
   177 {
       
   178     LoaderIndex index;
       
   179 
       
   180     /* See if we remembered the system loader */
       
   181     if ( loader==NULL && gdata->system_loader != 0 ) {
       
   182         return gdata->system_loader;
       
   183     }
       
   184     if ( loader==NULL ) {
       
   185         env = NULL;
       
   186     }
       
   187     index = search(env, loader);
       
   188     if ( index == 0 ) {
       
   189         static LoaderInfo  empty_info;
       
   190         LoaderInfo  info;
       
   191 
       
   192         info = empty_info;
       
   193         if ( loader != NULL ) {
       
   194             HPROF_ASSERT(env!=NULL);
       
   195             info.globalref = newWeakGlobalReference(env, loader);
       
   196             info.object_index = 0;
       
   197         }
       
   198         index = table_create_entry(gdata->loader_table, NULL, 0, (void*)&info);
       
   199     }
       
   200     HPROF_ASSERT(search(env,loader)==index);
       
   201     /* Remember the system loader */
       
   202     if ( loader==NULL && gdata->system_loader == 0 ) {
       
   203         gdata->system_loader = index;
       
   204     }
       
   205     return index;
       
   206 }
       
   207 
       
   208 void
       
   209 loader_init(void)
       
   210 {
       
   211     gdata->loader_table = table_initialize("Loader",
       
   212                             16, 16, 0, (int)sizeof(LoaderInfo));
       
   213 }
       
   214 
       
   215 void
       
   216 loader_list(void)
       
   217 {
       
   218     debug_message(
       
   219         "--------------------- Loader Table ------------------------\n");
       
   220     table_walk_items(gdata->loader_table, &list_item, NULL);
       
   221     debug_message(
       
   222         "----------------------------------------------------------\n");
       
   223 }
       
   224 
       
   225 void
       
   226 loader_cleanup(void)
       
   227 {
       
   228     table_cleanup(gdata->loader_table, &cleanup_item, NULL);
       
   229     gdata->loader_table = NULL;
       
   230 }
       
   231 
       
   232 void
       
   233 loader_delete_global_references(JNIEnv *env)
       
   234 {
       
   235     table_walk_items(gdata->loader_table, &delete_ref_item, (void*)env);
       
   236 }
       
   237 
       
   238 /* Get the object index for a class loader */
       
   239 ObjectIndex
       
   240 loader_object_index(JNIEnv *env, LoaderIndex index)
       
   241 {
       
   242     LoaderInfo *info;
       
   243     ObjectIndex object_index;
       
   244     jobject     wref;
       
   245 
       
   246     /* Assume no object index at first (default class loader) */
       
   247     info = get_info(index);
       
   248     object_index = info->object_index;
       
   249     wref = info->globalref;
       
   250     if ( wref != NULL && object_index == 0 ) {
       
   251         jobject lref;
       
   252 
       
   253         object_index = 0;
       
   254         lref = newLocalReference(env, wref);
       
   255         if ( lref != NULL && !isSameObject(env, lref, NULL) ) {
       
   256             jlong tag;
       
   257 
       
   258             /* Get the tag on the object and extract the object_index */
       
   259             tag = getTag(lref);
       
   260             if ( tag != (jlong)0 ) {
       
   261                 object_index = tag_extract(tag);
       
   262             }
       
   263         }
       
   264         if ( lref != NULL ) {
       
   265             deleteLocalReference(env, lref);
       
   266         }
       
   267         info->object_index = object_index;
       
   268     }
       
   269     return object_index;
       
   270 }