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