author | chegar |
Sun, 17 Aug 2014 15:54:13 +0100 | |
changeset 25859 | 3317bb8137f4 |
parent 23010 | jdk/src/share/demo/jvmti/hprof/hprof_class.c@6dadb192ad81 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
23010
6dadb192ad81
8029235: Update copyright year to match last edit in jdk8 jdk repository for 2013
lana
parents:
20823
diff
changeset
|
2 |
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
* |
|
5506 | 15 |
* - Neither the name of Oracle nor the names of its |
2 | 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 |
||
10292
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
32 |
/* |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
33 |
* This source code is provided to illustrate the usage of a given feature |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
34 |
* or technique and has been deliberately simplified. Additional steps |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
35 |
* required for a production-quality application, such as security checks, |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
36 |
* input validation and proper error handling, might not be present in |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
37 |
* this sample code. |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
38 |
*/ |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
39 |
|
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
40 |
|
2 | 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); |
|
20823 | 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 |
} |
|
2 | 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); |
|
20823 | 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 |
} |
|
2 | 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 |
} |