Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/hprof/hprof_event.c
38829 views
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
/* This file contains all class, method and allocation event support functions,
42
* both JVMTI and BCI events.
43
* (See hprof_monitor.c for the monitor event handlers).
44
*/
45
46
#include "hprof.h"
47
48
/* Private internal functions. */
49
50
/* Return a TraceIndex for the given thread. */
51
static TraceIndex
52
get_current(TlsIndex tls_index, JNIEnv *env, jboolean skip_init)
53
{
54
TraceIndex trace_index;
55
56
trace_index = tls_get_trace(tls_index, env, gdata->max_trace_depth, skip_init);
57
return trace_index;
58
}
59
60
/* Return a ClassIndex for the given jclass, loader supplied or looked up. */
61
static ClassIndex
62
find_cnum(JNIEnv *env, jclass klass, jobject loader)
63
{
64
LoaderIndex loader_index;
65
ClassIndex cnum;
66
char * signature;
67
68
HPROF_ASSERT(klass!=NULL);
69
70
/* Get the loader index */
71
loader_index = loader_find_or_create(env, loader);
72
73
/* Get the signature for this class */
74
getClassSignature(klass, &signature, NULL);
75
76
/* Find the ClassIndex for this class */
77
cnum = class_find_or_create(signature, loader_index);
78
79
/* Free the signature space */
80
jvmtiDeallocate(signature);
81
82
/* Make sure we save a global reference to this class in the table */
83
HPROF_ASSERT(cnum!=0);
84
(void)class_new_classref(env, cnum, klass);
85
return cnum;
86
}
87
88
/* Get the ClassIndex for the superClass of this jclass. */
89
static ClassIndex
90
get_super(JNIEnv *env, jclass klass)
91
{
92
ClassIndex super_cnum;
93
94
super_cnum = 0;
95
WITH_LOCAL_REFS(env, 1) {
96
jclass super_klass;
97
98
super_klass = getSuperclass(env, klass);
99
if ( super_klass != NULL ) {
100
super_cnum = find_cnum(env, super_klass,
101
getClassLoader(super_klass));
102
}
103
} END_WITH_LOCAL_REFS;
104
return super_cnum;
105
}
106
107
/* Record an allocation. Could be jobject, jclass, jarray or primitive type. */
108
static void
109
any_allocation(JNIEnv *env, SerialNumber thread_serial_num,
110
TraceIndex trace_index, jobject object)
111
{
112
SiteIndex site_index;
113
ClassIndex cnum;
114
jint size;
115
jclass klass;
116
117
/* NOTE: Normally the getObjectClass() and getClassLoader()
118
* would require a
119
* WITH_LOCAL_REFS(env, 1) {
120
* } END_WITH_LOCAL_REFS;
121
* but for performance reasons we skip it here.
122
*/
123
124
/* Get and tag the klass */
125
klass = getObjectClass(env, object);
126
cnum = find_cnum(env, klass, getClassLoader(klass));
127
site_index = site_find_or_create(cnum, trace_index);
128
tag_class(env, klass, cnum, thread_serial_num, site_index);
129
130
/* Tag the object */
131
size = (jint)getObjectSize(object);
132
tag_new_object(object, OBJECT_NORMAL, thread_serial_num, size, site_index);
133
}
134
135
/* Handle a java.lang.Object.<init> object allocation. */
136
void
137
event_object_init(JNIEnv *env, jthread thread, jobject object)
138
{
139
/* Called via BCI Tracker class */
140
141
/* Be very careful what is called here, watch out for recursion. */
142
143
jint *pstatus;
144
TraceIndex trace_index;
145
SerialNumber thread_serial_num;
146
147
HPROF_ASSERT(env!=NULL);
148
HPROF_ASSERT(thread!=NULL);
149
HPROF_ASSERT(object!=NULL);
150
151
/* Prevent recursion into any BCI function for this thread (pstatus). */
152
if ( tls_get_tracker_status(env, thread, JNI_TRUE,
153
&pstatus, NULL, &thread_serial_num, &trace_index) == 0 ) {
154
(*pstatus) = 1;
155
any_allocation(env, thread_serial_num, trace_index, object);
156
(*pstatus) = 0;
157
}
158
}
159
160
/* Handle any newarray opcode allocation. */
161
void
162
event_newarray(JNIEnv *env, jthread thread, jobject object)
163
{
164
/* Called via BCI Tracker class */
165
166
/* Be very careful what is called here, watch out for recursion. */
167
168
jint *pstatus;
169
TraceIndex trace_index;
170
SerialNumber thread_serial_num;
171
172
HPROF_ASSERT(env!=NULL);
173
HPROF_ASSERT(thread!=NULL);
174
HPROF_ASSERT(object!=NULL);
175
176
/* Prevent recursion into any BCI function for this thread (pstatus). */
177
if ( tls_get_tracker_status(env, thread, JNI_FALSE,
178
&pstatus, NULL, &thread_serial_num, &trace_index) == 0 ) {
179
(*pstatus) = 1;
180
any_allocation(env, thread_serial_num, trace_index, object);
181
(*pstatus) = 0;
182
}
183
}
184
185
/* Handle tracking of a method call. */
186
void
187
event_call(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum)
188
{
189
/* Called via BCI Tracker class */
190
191
/* Be very careful what is called here, watch out for recursion. */
192
193
TlsIndex tls_index;
194
jint *pstatus;
195
196
HPROF_ASSERT(env!=NULL);
197
HPROF_ASSERT(thread!=NULL);
198
if (cnum == 0 || cnum == gdata->tracker_cnum) {
199
jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
200
if ((*env)->ExceptionCheck(env)) {
201
(*env)->ExceptionClear(env);
202
HPROF_ERROR(JNI_TRUE,
203
"Could not find the java/lang/IllegalArgumentException class");
204
}
205
(*env)->ThrowNew(env, newExcCls, "Illegal cnum.");
206
207
return;
208
}
209
210
/* Prevent recursion into any BCI function for this thread (pstatus). */
211
if ( tls_get_tracker_status(env, thread, JNI_FALSE,
212
&pstatus, &tls_index, NULL, NULL) == 0 ) {
213
jmethodID method;
214
215
(*pstatus) = 1;
216
method = class_get_methodID(env, cnum, mnum);
217
if (method != NULL) {
218
tls_push_method(tls_index, method);
219
}
220
221
(*pstatus) = 0;
222
}
223
}
224
225
/* Handle tracking of an exception catch */
226
void
227
event_exception_catch(JNIEnv *env, jthread thread, jmethodID method,
228
jlocation location, jobject exception)
229
{
230
/* Called via JVMTI_EVENT_EXCEPTION_CATCH callback */
231
232
/* Be very careful what is called here, watch out for recursion. */
233
234
TlsIndex tls_index;
235
jint *pstatus;
236
237
HPROF_ASSERT(env!=NULL);
238
HPROF_ASSERT(thread!=NULL);
239
HPROF_ASSERT(method!=NULL);
240
241
/* Prevent recursion into any BCI function for this thread (pstatus). */
242
if ( tls_get_tracker_status(env, thread, JNI_FALSE,
243
&pstatus, &tls_index, NULL, NULL) == 0 ) {
244
(*pstatus) = 1;
245
tls_pop_exception_catch(tls_index, thread, method);
246
(*pstatus) = 0;
247
}
248
}
249
250
/* Handle tracking of a method return pop one (maybe more) methods. */
251
void
252
event_return(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum)
253
{
254
/* Called via BCI Tracker class */
255
256
/* Be very careful what is called here, watch out for recursion. */
257
258
TlsIndex tls_index;
259
jint *pstatus;
260
261
HPROF_ASSERT(env!=NULL);
262
HPROF_ASSERT(thread!=NULL);
263
264
if (cnum == 0 || cnum == gdata->tracker_cnum) {
265
jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
266
if ((*env)->ExceptionCheck(env)) {
267
(*env)->ExceptionClear(env);
268
HPROF_ERROR(JNI_TRUE,
269
"Could not find the java/lang/IllegalArgumentException class");
270
}
271
(*env)->ThrowNew(env, newExcCls, "Illegal cnum.");
272
273
return;
274
}
275
276
/* Prevent recursion into any BCI function for this thread (pstatus). */
277
if ( tls_get_tracker_status(env, thread, JNI_FALSE,
278
&pstatus, &tls_index, NULL, NULL) == 0 ) {
279
jmethodID method;
280
281
(*pstatus) = 1;
282
method = class_get_methodID(env, cnum, mnum);
283
if (method != NULL) {
284
tls_pop_method(tls_index, thread, method);
285
}
286
287
(*pstatus) = 0;
288
}
289
}
290
291
/* Handle a class prepare (should have been already loaded) */
292
void
293
event_class_prepare(JNIEnv *env, jthread thread, jclass klass, jobject loader)
294
{
295
/* Called via JVMTI_EVENT_CLASS_PREPARE event */
296
297
ClassIndex cnum;
298
299
HPROF_ASSERT(env!=NULL);
300
HPROF_ASSERT(thread!=NULL);
301
HPROF_ASSERT(klass!=NULL);
302
303
/* Find the ClassIndex for this class */
304
cnum = find_cnum(env, klass, loader);
305
class_add_status(cnum, CLASS_PREPARED);
306
307
}
308
309
/* Handle a class load (could have been already loaded) */
310
void
311
event_class_load(JNIEnv *env, jthread thread, jclass klass, jobject loader)
312
{
313
/* Called via JVMTI_EVENT_CLASS_LOAD event or reset_class_load_status() */
314
315
ClassIndex cnum;
316
317
HPROF_ASSERT(env!=NULL);
318
HPROF_ASSERT(klass!=NULL);
319
320
/* Find the ClassIndex for this class */
321
cnum = find_cnum(env, klass, loader);
322
323
/* Always mark it as being in the load list */
324
class_add_status(cnum, CLASS_IN_LOAD_LIST);
325
326
/* If we are seeing this as a new loaded class, extra work */
327
if ( ! ( class_get_status(cnum) & CLASS_LOADED ) ) {
328
TraceIndex trace_index;
329
SiteIndex site_index;
330
ClassIndex super;
331
SerialNumber class_serial_num;
332
SerialNumber trace_serial_num;
333
SerialNumber thread_serial_num;
334
ObjectIndex class_object_index;
335
char *signature;
336
337
/* Get the TlsIndex and a TraceIndex for this location */
338
if ( thread == NULL ) {
339
/* This should be very rare, but if this class load was simulated
340
* from hprof_init.c due to a reset of the class load status,
341
* and it originated from a pre-VM_INIT event, the jthread
342
* would be NULL, or it was a jclass created that didn't get
343
* reported to us, like an array class or a primitive class?
344
*/
345
trace_index = gdata->system_trace_index;
346
thread_serial_num = gdata->unknown_thread_serial_num;
347
} else {
348
TlsIndex tls_index;
349
350
tls_index = tls_find_or_create(env, thread);
351
trace_index = get_current(tls_index, env, JNI_FALSE);
352
thread_serial_num = tls_get_thread_serial_number(tls_index);
353
}
354
355
/* Get the SiteIndex for this location and a java.lang.Class object */
356
/* Note that the target cnum, not the cnum for java.lang.Class. */
357
site_index = site_find_or_create(cnum, trace_index);
358
359
/* Tag this java.lang.Class object */
360
tag_class(env, klass, cnum, thread_serial_num, site_index);
361
362
class_add_status(cnum, CLASS_LOADED);
363
364
class_serial_num = class_get_serial_number(cnum);
365
class_object_index = class_get_object_index(cnum);
366
trace_serial_num = trace_get_serial_number(trace_index);
367
signature = string_get(class_get_signature(cnum));
368
369
rawMonitorEnter(gdata->data_access_lock); {
370
io_write_class_load(class_serial_num, class_object_index,
371
trace_serial_num, signature);
372
} rawMonitorExit(gdata->data_access_lock);
373
374
super = get_super(env, klass);
375
class_set_super(cnum, super);
376
}
377
378
}
379
380
/* Handle a thread start event */
381
void
382
event_thread_start(JNIEnv *env, jthread thread)
383
{
384
/* Called via JVMTI_EVENT_THREAD_START event */
385
386
TlsIndex tls_index;
387
ObjectIndex object_index;
388
TraceIndex trace_index;
389
jlong tag;
390
SerialNumber thread_serial_num;
391
392
HPROF_ASSERT(env!=NULL);
393
HPROF_ASSERT(thread!=NULL);
394
395
tls_index = tls_find_or_create(env, thread);
396
thread_serial_num = tls_get_thread_serial_number(tls_index);
397
trace_index = get_current(tls_index, env, JNI_FALSE);
398
399
tag = getTag(thread);
400
if ( tag == (jlong)0 ) {
401
SiteIndex site_index;
402
jint size;
403
404
size = (jint)getObjectSize(thread);
405
site_index = site_find_or_create(gdata->thread_cnum, trace_index);
406
/* We create a new object with this thread's serial number */
407
object_index = object_new(site_index, size, OBJECT_NORMAL,
408
thread_serial_num);
409
} else {
410
object_index = tag_extract(tag);
411
/* Normally the Thread object is created and tagged before we get
412
* here, but the thread_serial_number on this object isn't what
413
* we want. So we update it to the serial number of this thread.
414
*/
415
object_set_thread_serial_number(object_index, thread_serial_num);
416
}
417
tls_set_thread_object_index(tls_index, object_index);
418
419
WITH_LOCAL_REFS(env, 1) {
420
jvmtiThreadInfo threadInfo;
421
jvmtiThreadGroupInfo threadGroupInfo;
422
jvmtiThreadGroupInfo parentGroupInfo;
423
424
getThreadInfo(thread, &threadInfo);
425
getThreadGroupInfo(threadInfo.thread_group, &threadGroupInfo);
426
if ( threadGroupInfo.parent != NULL ) {
427
getThreadGroupInfo(threadGroupInfo.parent, &parentGroupInfo);
428
} else {
429
(void)memset(&parentGroupInfo, 0, sizeof(parentGroupInfo));
430
}
431
432
rawMonitorEnter(gdata->data_access_lock); {
433
io_write_thread_start(thread_serial_num,
434
object_index, trace_get_serial_number(trace_index),
435
threadInfo.name, threadGroupInfo.name, parentGroupInfo.name);
436
} rawMonitorExit(gdata->data_access_lock);
437
438
jvmtiDeallocate(threadInfo.name);
439
jvmtiDeallocate(threadGroupInfo.name);
440
jvmtiDeallocate(parentGroupInfo.name);
441
442
} END_WITH_LOCAL_REFS;
443
}
444
445
void
446
event_thread_end(JNIEnv *env, jthread thread)
447
{
448
/* Called via JVMTI_EVENT_THREAD_END event */
449
TlsIndex tls_index;
450
451
HPROF_ASSERT(env!=NULL);
452
HPROF_ASSERT(thread!=NULL);
453
454
tls_index = tls_find_or_create(env, thread);
455
rawMonitorEnter(gdata->data_access_lock); {
456
io_write_thread_end(tls_get_thread_serial_number(tls_index));
457
} rawMonitorExit(gdata->data_access_lock);
458
tls_thread_ended(env, tls_index);
459
setThreadLocalStorage(thread, (void*)NULL);
460
}
461
462