Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FramePop/framepop002/framepop002.cpp
40955 views
1
/*
2
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include "jvmti.h"
28
#include "agent_common.h"
29
#include "JVMTITools.h"
30
#include "jvmti_tools.h"
31
32
extern "C" {
33
34
35
#define PASSED 0
36
#define STATUS_FAILED 2
37
#define MAX_THREADS 32
38
39
typedef struct item *item_t;
40
struct item {
41
item_t next;
42
jmethodID method;
43
int depth;
44
} item;
45
46
typedef struct thr {
47
jthread thread;
48
item_t tos;
49
} thr;
50
51
static jvmtiEnv *jvmti = NULL;
52
static jvmtiCapabilities caps;
53
static jvmtiEventCallbacks callbacks;
54
static jrawMonitorID event_lock;
55
static jint result = PASSED;
56
static jboolean printdump = JNI_FALSE;
57
static jboolean watch_events = JNI_FALSE;
58
59
static int pop_count = 0;
60
static int push_count = 0;
61
static int thr_count = 0;
62
static int max_depth = 0;
63
static thr threads[MAX_THREADS];
64
65
static volatile int callbacksEnabled = NSK_FALSE;
66
static jrawMonitorID agent_lock;
67
68
static
69
int isTestThread(jvmtiEnv *jvmti_env, jthread thr) {
70
jvmtiError err;
71
jvmtiThreadInfo inf;
72
const char* TEST_THREAD_NAME_BASE = "Test Thread";
73
74
err = jvmti_env->GetThreadInfo(thr, &inf);
75
if (err != JVMTI_ERROR_NONE) {
76
printf("(GetThreadInfo) unexpected error: %s (%d)\n", TranslateError(err), err);
77
result = STATUS_FAILED;
78
return 0;
79
}
80
return strncmp(inf.name, TEST_THREAD_NAME_BASE, strlen(TEST_THREAD_NAME_BASE)) == 0;
81
}
82
83
static
84
void printInfo(jvmtiEnv *jvmti_env, jthread thr, jmethodID method, int depth) {
85
jvmtiError err;
86
jvmtiThreadInfo inf;
87
char *clsig, *name, *sig, *generic;
88
jclass cls;
89
90
err = jvmti_env->GetThreadInfo(thr, &inf);
91
if (err != JVMTI_ERROR_NONE) {
92
printf("(GetThreadInfo) unexpected error: %s (%d)\n",
93
TranslateError(err), err);
94
result = STATUS_FAILED;
95
}
96
97
err = jvmti_env->GetMethodDeclaringClass(method, &cls);
98
if (err != JVMTI_ERROR_NONE) {
99
printf("(GetMethodDeclaringClass) unexpected error: %s (%d)\n",
100
TranslateError(err), err);
101
result = STATUS_FAILED;
102
return;
103
}
104
105
err = jvmti_env->GetClassSignature(cls, &clsig, &generic);
106
if (err != JVMTI_ERROR_NONE) {
107
printf("(GetClassSignature) unexpected error: %s (%d)\n",
108
TranslateError(err), err);
109
result = STATUS_FAILED;
110
return;
111
}
112
113
err = jvmti_env->GetMethodName(method, &name, &sig, &generic);
114
if (err != JVMTI_ERROR_NONE) {
115
printf("(GetMethodName) unexpected error: %s (%d)\n",
116
TranslateError(err), err);
117
result = STATUS_FAILED;
118
return;
119
}
120
121
printf(" %s: %s.%s%s, depth = %d\n", inf.name, clsig, name, sig, depth);
122
123
jvmti_env->Deallocate((unsigned char *)sig);
124
jvmti_env->Deallocate((unsigned char *)name);
125
jvmti_env->Deallocate((unsigned char *)clsig);
126
jvmti_env->Deallocate((unsigned char *)inf.name);
127
}
128
129
static
130
void pop(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr, jmethodID method, int depth) {
131
item_t old;
132
int i, count = 0;
133
134
for (i = 0; i < thr_count; i++) {
135
if (env->IsSameObject(threads[i].thread, thr)) {
136
break;
137
}
138
}
139
140
if (i == thr_count) {
141
watch_events = JNI_FALSE;
142
printf("Unknown thread:\n");
143
printInfo(jvmti_env, thr, method, depth);
144
result = STATUS_FAILED;
145
return;
146
}
147
148
if (threads[i].tos == NULL) {
149
watch_events = JNI_FALSE;
150
printf("Stack underflow:\n");
151
printInfo(jvmti_env, thr, method, depth);
152
result = STATUS_FAILED;
153
return;
154
}
155
156
do {
157
pop_count++;
158
old = threads[i].tos;
159
threads[i].tos = threads[i].tos->next;
160
if (old->method == method && old->depth == depth) {
161
free(old);
162
return;
163
}
164
free(old);
165
} while (threads[i].tos != NULL);
166
167
watch_events = JNI_FALSE;
168
printf("Frame pop does not match any entry:\n");
169
printInfo(jvmti_env, thr, method, depth);
170
result = STATUS_FAILED;
171
}
172
173
static
174
void push(JNIEnv *env, jthread thr, jmethodID method, int depth) {
175
item_t new_item;
176
int i;
177
178
for (i = 0; i < thr_count; i++) {
179
if (env->IsSameObject(threads[i].thread, thr)) {
180
break;
181
}
182
}
183
184
if (i == thr_count) {
185
thr_count++;
186
if (thr_count == MAX_THREADS) {
187
watch_events = JNI_FALSE;
188
printf("Out of threads\n");
189
result = STATUS_FAILED;
190
return;
191
}
192
threads[i].thread = env->NewGlobalRef(thr);
193
threads[i].tos = NULL;
194
}
195
196
new_item = (item_t)malloc(sizeof(item));
197
if (new_item == NULL) {
198
watch_events = JNI_FALSE;
199
printf("Out of memory\n");
200
result = STATUS_FAILED;
201
return;
202
}
203
204
new_item->next = threads[i].tos;
205
new_item->method = method;
206
new_item->depth = depth;
207
threads[i].tos = new_item;
208
push_count++;
209
max_depth = (max_depth < depth) ? depth : max_depth;
210
}
211
212
void JNICALL MethodEntry(jvmtiEnv *jvmti_env, JNIEnv *env,
213
jthread thr, jmethodID method) {
214
jvmtiError err;
215
jboolean isNative;
216
jint frameCount;
217
218
if (watch_events == JNI_FALSE) return;
219
220
jvmti->RawMonitorEnter(agent_lock);
221
222
if (!callbacksEnabled) {
223
jvmti->RawMonitorExit(agent_lock);
224
return;
225
}
226
227
err = jvmti_env->GetFrameCount(thr, &frameCount);
228
if (err != JVMTI_ERROR_NONE) {
229
printf("(GetFrameCount#entry) unexpected error: %s (%d)\n",
230
TranslateError(err), err);
231
printInfo(jvmti_env, thr, method, frameCount);
232
result = STATUS_FAILED;
233
jvmti->RawMonitorExit(agent_lock);
234
return;
235
}
236
237
err = jvmti_env->IsMethodNative(method, &isNative);
238
if (err != JVMTI_ERROR_NONE) {
239
printf("(IsMethodNative) unexpected error: %s (%d)\n",
240
TranslateError(err), err);
241
printInfo(jvmti_env, thr, method, frameCount);
242
result = STATUS_FAILED;
243
}
244
245
if (isTestThread(jvmti_env, thr)) {
246
if (printdump == JNI_TRUE) {
247
printf(">>> %sMethod entry\n>>>",
248
(isNative == JNI_TRUE) ? "Native " : "");
249
printInfo(jvmti_env, thr, method, frameCount);
250
}
251
if (isNative == JNI_FALSE) {
252
err = jvmti_env->RawMonitorEnter(event_lock);
253
if (err != JVMTI_ERROR_NONE) {
254
printf("(RawMonitorEnter) unexpected error: %s (%d)\n",
255
TranslateError(err), err);
256
printInfo(jvmti_env, thr, method, frameCount);
257
result = STATUS_FAILED;
258
}
259
push((JNIEnv *)env, thr, method, frameCount);
260
err = jvmti_env->RawMonitorExit(event_lock);
261
if (err != JVMTI_ERROR_NONE) {
262
printf("(RawMonitorExit) unexpected error: %s (%d)\n",
263
TranslateError(err), err);
264
printInfo(jvmti_env, thr, method, frameCount);
265
result = STATUS_FAILED;
266
}
267
err = jvmti_env->NotifyFramePop(thr, 0);
268
if (err != JVMTI_ERROR_NONE) {
269
printf("(NotifyFramePop) unexpected error: %s (%d)\n",
270
TranslateError(err), err);
271
printInfo(jvmti_env, thr, method, frameCount);
272
result = STATUS_FAILED;
273
}
274
}
275
}
276
277
jvmti->RawMonitorExit(agent_lock);
278
}
279
280
void JNICALL VMStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {
281
jvmti->RawMonitorEnter(agent_lock);
282
283
callbacksEnabled = NSK_TRUE;
284
285
jvmti->RawMonitorExit(agent_lock);
286
}
287
288
289
void JNICALL VMDeath(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {
290
jvmti->RawMonitorEnter(agent_lock);
291
292
callbacksEnabled = NSK_FALSE;
293
294
jvmti->RawMonitorExit(agent_lock);
295
}
296
297
void JNICALL FramePop(jvmtiEnv *jvmti_env, JNIEnv *env,
298
jthread thr, jmethodID method, jboolean wasPopedByException) {
299
jvmtiError err;
300
jint frameCount;
301
302
jvmti->RawMonitorEnter(agent_lock);
303
304
if (!callbacksEnabled) {
305
jvmti->RawMonitorExit(agent_lock);
306
return;
307
}
308
err = jvmti_env->GetFrameCount(thr, &frameCount);
309
if (err != JVMTI_ERROR_NONE) {
310
printf("(GetFrameCount#entry) unexpected error: %s (%d)\n",
311
TranslateError(err), err);
312
printInfo(jvmti_env, thr, method, frameCount);
313
result = STATUS_FAILED;
314
jvmti->RawMonitorExit(agent_lock);
315
return;
316
}
317
318
if (isTestThread(jvmti_env, thr)) {
319
if (printdump == JNI_TRUE) {
320
printf(">>> Frame Pop\n>>>");
321
printInfo(jvmti_env, thr, method, frameCount);
322
}
323
err = jvmti_env->RawMonitorEnter(event_lock);
324
if (err != JVMTI_ERROR_NONE) {
325
printf("(RawMonitorEnter) unexpected error: %s (%d)\n",
326
TranslateError(err), err);
327
printInfo(jvmti_env, thr, method, frameCount);
328
result = STATUS_FAILED;
329
}
330
pop(jvmti_env, (JNIEnv *)env, thr, method, frameCount);
331
err = jvmti_env->RawMonitorExit(event_lock);
332
if (err != JVMTI_ERROR_NONE) {
333
printf("(RawMonitorExit) unexpected error: %s (%d)\n",
334
TranslateError(err), err);
335
printInfo(jvmti_env, thr, method, frameCount);
336
result = STATUS_FAILED;
337
}
338
}
339
340
jvmti->RawMonitorExit(agent_lock);
341
}
342
343
#ifdef STATIC_BUILD
344
JNIEXPORT jint JNICALL Agent_OnLoad_framepop002(JavaVM *jvm, char *options, void *reserved) {
345
return Agent_Initialize(jvm, options, reserved);
346
}
347
JNIEXPORT jint JNICALL Agent_OnAttach_framepop002(JavaVM *jvm, char *options, void *reserved) {
348
return Agent_Initialize(jvm, options, reserved);
349
}
350
JNIEXPORT jint JNI_OnLoad_framepop002(JavaVM *jvm, char *options, void *reserved) {
351
return JNI_VERSION_1_8;
352
}
353
#endif
354
jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
355
jvmtiError err;
356
jint res;
357
358
if (options != NULL && strcmp(options, "printdump") == 0) {
359
printdump = JNI_TRUE;
360
}
361
362
res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
363
if (res != JNI_OK || jvmti == NULL) {
364
printf("Wrong result of a valid call to GetEnv!\n");
365
return JNI_ERR;
366
}
367
368
err = jvmti->CreateRawMonitor("_event_lock", &event_lock);
369
if (err != JVMTI_ERROR_NONE) {
370
printf("(CreateRawMonitor) unexpected error: %s (%d)\n",
371
TranslateError(err), err);
372
return JNI_ERR;
373
}
374
375
err = jvmti->GetPotentialCapabilities(&caps);
376
if (err != JVMTI_ERROR_NONE) {
377
printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n",
378
TranslateError(err), err);
379
return JNI_ERR;
380
}
381
382
err = jvmti->AddCapabilities(&caps);
383
if (err != JVMTI_ERROR_NONE) {
384
printf("(AddCapabilities) unexpected error: %s (%d)\n",
385
TranslateError(err), err);
386
return JNI_ERR;
387
}
388
389
err = jvmti->GetCapabilities(&caps);
390
if (err != JVMTI_ERROR_NONE) {
391
printf("(GetCapabilities) unexpected error: %s (%d)\n",
392
TranslateError(err), err);
393
return JNI_ERR;
394
}
395
396
if (caps.can_generate_frame_pop_events &&
397
caps.can_generate_method_entry_events) {
398
callbacks.MethodEntry = &MethodEntry;
399
callbacks.FramePop = &FramePop;
400
callbacks.VMStart = &VMStart;
401
callbacks.VMDeath = &VMDeath;
402
403
err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
404
if (err != JVMTI_ERROR_NONE) {
405
printf("(SetEventCallbacks) unexpected error: %s (%d)\n",
406
TranslateError(err), err);
407
return JNI_ERR;
408
}
409
if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_START, NULL)))
410
return JNI_ERR;
411
if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL)))
412
return JNI_ERR;
413
414
if (jvmti->CreateRawMonitor("agent_lock", &agent_lock) != JVMTI_ERROR_NONE) {
415
return JNI_ERR;
416
}
417
418
} else {
419
printf("Warning: FramePop or MethodEntry event is not implemented\n");
420
}
421
422
return JNI_OK;
423
}
424
425
JNIEXPORT void JNICALL Java_nsk_jvmti_FramePop_framepop002_getReady(JNIEnv *env, jclass cls) {
426
jvmtiError err;
427
428
if (!caps.can_generate_frame_pop_events ||
429
!caps.can_generate_method_entry_events) {
430
return ;
431
}
432
433
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
434
JVMTI_EVENT_METHOD_ENTRY, NULL);
435
if (err != JVMTI_ERROR_NONE) {
436
printf("Failed to enable JVMTI_EVENT_METHOD_ENTRY event: %s (%d)\n",
437
TranslateError(err), err);
438
result = STATUS_FAILED;
439
}
440
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
441
JVMTI_EVENT_FRAME_POP, NULL);
442
if (err != JVMTI_ERROR_NONE) {
443
printf("Failed to enable JVMTI_EVENT_FRAME_POP event: %s (%d)\n",
444
TranslateError(err), err);
445
result = STATUS_FAILED;
446
}
447
watch_events = JNI_TRUE;
448
}
449
450
JNIEXPORT jint JNICALL Java_nsk_jvmti_FramePop_framepop002_check(JNIEnv *env, jclass cls) {
451
jvmtiError err;
452
453
watch_events = JNI_FALSE;
454
err = jvmti->SetEventNotificationMode(JVMTI_DISABLE,
455
JVMTI_EVENT_FRAME_POP, NULL);
456
if (err != JVMTI_ERROR_NONE) {
457
printf("Failed to disable JVMTI_EVENT_FRAME_POP event: %s (%d)\n",
458
TranslateError(err), err);
459
result = STATUS_FAILED;
460
}
461
err = jvmti->SetEventNotificationMode(JVMTI_DISABLE,
462
JVMTI_EVENT_METHOD_ENTRY, NULL);
463
if (err != JVMTI_ERROR_NONE) {
464
printf("Failed to disable JVMTI_EVENT_METHOD_ENTRY event: %s (%d)\n",
465
TranslateError(err), err);
466
result = STATUS_FAILED;
467
}
468
469
if (printdump == JNI_TRUE) {
470
printf("%d threads, %d method entrys, %d frame pops, max depth = %d\n",
471
thr_count, push_count, pop_count, max_depth);
472
}
473
474
return result;
475
}
476
477
}
478
479