1 /*
2 * Copyright (c) 2003, 2019, 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 <stdlib.h>
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <ctype.h>
29
30 /*************************************************************/
31
32 #include "jvmti.h"
33
34 /*************************************************************/
35
36 #include "nsk_tools.h"
37 #include "jni_tools.h"
38 #include "jvmti_tools.h"
39 #include "JVMTITools.h"
40
41 /*************************************************************/
42
43 extern "C" {
44
45 /*************************************************************/
46
47 #define NSK_JVMTI_WAITTIME 2
48
49 #define NSK_JVMTI_MAX_OPTIONS 10
50 #define NSK_JVMTI_OPTION_START '-'
51
52 #define NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE "pathToNewByteCode"
53 #define PATH_FORMAT "%s%02d/%s"
54 #define DIR_NAME "newclass"
55
56 static volatile int redefineAttempted = NSK_FALSE;
57 static volatile int redefineSucceed = NSK_FALSE;
58 static volatile int agentFailed = NSK_FALSE;
59
60 static struct {
61 struct {
62 int count;
63 char* names[NSK_JVMTI_MAX_OPTIONS];
64 char* values[NSK_JVMTI_MAX_OPTIONS];
65 char* string;
66 } options;
67 int waittime;
68 } context;
69
70 /*************************************************************/
71
check_option(int dashed,const char name[],const char value[])72 static int check_option(int dashed, const char name[], const char value[]) {
73 if (strcmp("verbose", name) == 0) {
74 if (strlen(value) > 0) {
75 nsk_complain("nsk_jvmti_parseOptions(): unexpected value in option: %s=%s\n", name, value);
76 return NSK_FALSE;
77 }
78 nsk_setVerboseMode(NSK_TRUE);
79 } else if (strcmp("trace", name) == 0) {
80 if (strlen(value) <= 0) {
81 nsk_complain("nsk_jvmti_parseOptions(): no value for option: %s\n", name);
82 return NSK_FALSE;
83 }
84 if (strcmp("none", value) == 0) {
85 nsk_setTraceMode(NSK_TRACE_NONE);
86 } else if (strcmp("before", value) == 0) {
87 nsk_setTraceMode(NSK_TRACE_BEFORE);
88 } else if (strcmp("after", value) == 0) {
89 nsk_setTraceMode(NSK_TRACE_AFTER);
90 } else if (strcmp("all", value) == 0) {
91 nsk_setTraceMode(NSK_TRACE_ALL);
92 } else {
93 nsk_complain("nsk_jvmti_parseOptions(): uexpected value in option: %s=%s\n", name, value);
94 return NSK_FALSE;
95 }
96 nsk_setVerboseMode(NSK_TRUE);
97 } else if (strcmp("waittime", name) == 0) {
98 if (strlen(value) <= 0) {
99 nsk_complain("nsk_jvmti_parseOptions(): no value for option: %s\n", name);
100 return NSK_FALSE;
101 }
102 {
103 char* end = NULL;
104 long n = strtol(value, &end, 10);
105 if (end == NULL || end == value || *end != '\0') {
106 nsk_complain("nsk_jvmti_parseOptions(): not integer value in option: %s=%s\n", name, value);
107 return NSK_FALSE;
108 }
109 if (n < 0) {
110 nsk_complain("nsk_jvmti_parseOptions(): negative value in option: %s=%s\n", name, value);
111 return NSK_FALSE;
112 }
113 context.waittime = (int)n;
114 }
115 } else if (dashed) {
116 nsk_complain("nsk_jvmti_parseOptions(): unknown option: %c%s\n",
117 NSK_JVMTI_OPTION_START, name);
118 return NSK_FALSE;
119 }
120 return NSK_TRUE;
121 }
122
add_option(const char opt[],int opt_len,const char val[],int val_len)123 static int add_option(const char opt[], int opt_len, const char val[], int val_len) {
124 char* name;
125 char* value;
126
127 int success = NSK_TRUE;
128 int dashed_opt = NSK_FALSE;
129
130 if (opt[0] == NSK_JVMTI_OPTION_START) {
131 dashed_opt = NSK_TRUE;
132 opt++;
133 opt_len--;
134 }
135 if (opt_len <= 0) {
136 nsk_complain("nsk_jvmti_parseOptions(): found empty option\n");
137 return NSK_FALSE;
138 }
139
140 name = (char*)malloc(opt_len + 1);
141 value = (char*)malloc(val_len + 1);
142
143 if (name == NULL || value == NULL) {
144 nsk_complain("nsk_jvmti_parseOptions(): out of memory\n");
145 success = NSK_FALSE;
146 } else {
147 strncpy(name, opt, opt_len);
148 name[opt_len] = '\0';
149 strncpy(value, val, val_len);
150 value[val_len] = '\0';
151
152 if (!check_option(dashed_opt, name, value)) {
153 success = NSK_FALSE;
154 }
155 }
156
157 if (success) {
158 if (context.options.count >= NSK_JVMTI_MAX_OPTIONS) {
159 nsk_complain("nsk_jvmti_parseOptions(): too many options for parsing\n");
160 success = NSK_FALSE;
161 } else {
162 context.options.names[context.options.count] = name;
163 context.options.values[context.options.count] = value;
164 context.options.count++;
165 }
166 }
167
168 if (!success) {
169 if (name != NULL)
170 free(name);
171 if (value != NULL)
172 free(value);
173 }
174
175 return success;
176 }
177
nsk_jvmti_free()178 static void nsk_jvmti_free() {
179 if (context.options.count > 0) {
180 int i;
181 for (i = 0; i < context.options.count; i++) {
182 free(context.options.names[i]);
183 free(context.options.values[i]);
184 }
185 context.options.count = 0;
186 }
187 if (context.options.string != NULL) {
188 free(context.options.string);
189 context.options.string = NULL;
190 }
191 }
192
193
194 /*
195 * Tokenize a string based on a list of delimiters.
196 */
token(char ** s,const char * delim)197 static char* token(char **s, const char *delim) {
198 char *p;
199 char *start = *s;
200
201 if (s == NULL || *s == NULL) {
202 return NULL;
203 }
204
205 p = strpbrk(*s, delim);
206 if (p != NULL) {
207 /* Advance to next token. */
208 *p = '\0';
209 *s = p + 1;
210 } else {
211 /* End of tokens. */
212 *s = NULL;
213 }
214
215 return start;
216 }
217
nsk_jvmti_parseOptions(const char options[])218 int nsk_jvmti_parseOptions(const char options[]) {
219 int success = NSK_TRUE;
220
221 char *str = NULL;
222 char *name = NULL;
223 char *value = NULL;
224 const char *delimiters = " ,~";
225 if (options == NULL)
226 return success;
227
228 /*
229 * Save a copy of the full options string for
230 * ArgumentHandler.getAgentOptionsString().
231 */
232 context.options.string = strdup(options);
233
234 /* Create a temporary copy of the options string to be tokenized. */
235 str = strdup(options);
236 while ((name = token(&str, delimiters)) != NULL) {
237 value = strchr(name, '=');
238
239 if (value != NULL) {
240 *value++ = '\0';
241 }
242 if (!add_option(name, (int)strlen(name), value,
243 value ? (int)strlen(value) : 0)) {
244 success = NSK_FALSE;
245 break;
246 }
247 }
248 if (!success) {
249 nsk_jvmti_free();
250 }
251 if (str != NULL) {
252 free(str);
253 }
254 return success;
255 }
256
257 /*************************************************************/
258
259 /**
260 * Returns value of given option name; or NULL if no such option found.
261 * If search name is NULL then complains an error and returns NULL.
262 */
nsk_jvmti_findOptionValue(const char name[])263 const char* nsk_jvmti_findOptionValue(const char name[]) {
264 int i;
265
266 if (name == NULL) {
267 nsk_complain("nsk_jvmti_findOptionValue(): option name is NULL\n");
268 return NULL;
269 }
270
271 for (i = 0; i < context.options.count; i++) {
272 if (strcmp(name, context.options.names[i]) == 0)
273 return context.options.values[i];
274 }
275 return NULL;
276 }
277
278 /**
279 * Returns string value of given option; or defaultValue if no such option found.
280 * If options is specified but has empty value then complains an error and returns NULL.
281 */
nsk_jvmti_findOptionStringValue(const char name[],const char * defaultValue)282 const char* nsk_jvmti_findOptionStringValue(const char name[], const char* defaultValue) {
283 const char* value;
284
285 if (name == NULL) {
286 nsk_complain("nsk_jvmti_findOptionStringValue(): option name is NULL\n");
287 return NULL;
288 }
289
290 value = nsk_jvmti_findOptionValue(name);
291 if (value == NULL) {
292 return defaultValue;
293 }
294
295 if (strlen(value) <= 0) {
296 nsk_complain("nsk_jvmti_findOptionStringValue(): empty value of option: %s=%s\n",
297 name, value);
298 return NULL;
299 }
300 return value;
301 }
302
303 /**
304 * Returns integer value of given option; or defaultValue if no such option found.
305 * If options is specified but has no integer value then complains an error and returns -1.
306 */
nsk_jvmti_findOptionIntValue(const char name[],int defaultValue)307 int nsk_jvmti_findOptionIntValue(const char name[], int defaultValue) {
308 const char* value;
309
310 if (name == NULL) {
311 nsk_complain("nsk_jvmti_findOptionIntValue(): option name is NULL\n");
312 return -1;
313 }
314
315 value = nsk_jvmti_findOptionValue(name);
316 if (value == NULL) {
317 return defaultValue;
318 }
319
320 if (strlen(value) <= 0) {
321 nsk_complain("nsk_jvmti_findOptionIntValue(): empty value of option: %s=%s\n",
322 name, value);
323 return -1;
324 }
325
326 {
327 char* endptr = NULL;
328 int n = strtol(value, &endptr, 10);
329
330 if (endptr == NULL || *endptr != '\0') {
331 nsk_complain("nsk_jvmti_findOptionIntValue(): not integer value of option: %s=%s\n",
332 name, value);
333 return -1;
334 }
335 return n;
336 }
337 }
338
339 /**
340 * Returns number of parsed options.
341 */
nsk_jvmti_getOptionsCount()342 int nsk_jvmti_getOptionsCount() {
343 return context.options.count;
344 }
345
346 /**
347 * Returns name of i-th parsed option.
348 * If no such option then complains an error and returns NULL.
349 */
nsk_jvmti_getOptionName(int i)350 const char* nsk_jvmti_getOptionName(int i) {
351 if (i < 0 || i >= context.options.count) {
352 nsk_complain("nsk_jvmti_getOptionName(): option index out of bounds: %d\n", i);
353 return NULL;
354 }
355 return context.options.names[i];
356 }
357
358 /**
359 * Returns value of i-th parsed option.
360 * If no such option then complains an error and returns NULL.
361 */
nsk_jvmti_getOptionValue(int i)362 const char* nsk_jvmti_getOptionValue(int i) {
363 if (i < 0 || i >= context.options.count) {
364 nsk_complain("nsk_jvmti_getOptionValue(): option index out of bounds: %d\n", i);
365 return NULL;
366 }
367 return context.options.values[i];
368 }
369
370 /*************************************************************/
371
372 /**
373 * Returns value of -waittime option or default value if not specified.
374 */
nsk_jvmti_getWaitTime()375 int nsk_jvmti_getWaitTime() {
376 return context.waittime;
377 }
378
379 /**
380 * Sets specified waittime value.
381 */
nsk_jvmti_setWaitTime(int waittime)382 void nsk_jvmti_setWaitTime(int waittime) {
383 context.waittime = waittime;
384 }
385
386 /*************************************************************/
387
nsk_jvmti_lverify(int positive,jvmtiError error,jvmtiError expected,const char file[],int line,const char format[],...)388 int nsk_jvmti_lverify(int positive, jvmtiError error, jvmtiError expected,
389 const char file[], int line, const char format[], ...)
390 {
391 int failure=0;
392 int negative = !positive;
393 int errorCode = (int)error;
394 const char* errorName = TranslateError(error);
395 va_list ap;
396 va_start(ap,format);
397 nsk_lvtrace(NSK_TRACE_AFTER,file,line,format,ap);
398 if (negative || expected != JVMTI_ERROR_NONE)
399 nsk_ltrace(NSK_TRACE_AFTER,file,line,
400 " jvmti error: code=%d, name=%s\n",errorCode,errorName);
401 if ((error == expected) == negative) {
402 nsk_lvcomplain(file,line,format,ap);
403 nsk_printf("# jvmti error: code=%d, name=%s\n",errorCode,errorName);
404 if (expected != JVMTI_ERROR_NONE)
405 nsk_printf("# error expected: code=%d, name=%s\n",
406 expected, TranslateError(expected));
407 failure=1;
408 };
409 va_end(ap);
410 return !failure;
411 }
412
413 /*************************************************************/
414
415 JNIEXPORT jstring JNICALL
Java_nsk_share_jvmti_ArgumentHandler_getAgentOptionsString(JNIEnv * jni,jobject obj)416 Java_nsk_share_jvmti_ArgumentHandler_getAgentOptionsString(JNIEnv *jni, jobject obj) {
417 jstring str_obj = NULL;
418
419 if (!NSK_JNI_VERIFY(jni, (str_obj = jni->NewStringUTF(context.options.string)) != NULL)) {
420 return NULL;
421 }
422 return str_obj;
423 }
424
425 /*************************************************************/
426
427 /**
428 * This method will try to redefine the class (classToRedefine) by loading
429 * physical file. <b>pathToNewByteCode</b> option which is passed
430 * on OnLoad Phase also used.
431 *
432 * So This method will do a file read pathToByteCode+fileName+.class (total path).
433 * Constrcuts a class objects and does a redefine of the class.
434 * On successfull redefine this method will return eaither JNI_TRUE or JNI_FALSE
435 *
436 * Hint::
437 * 1)
438 * If there are many redefine on same testcase, then please try to use
439 * integer value (newclass00, newclass01, newclass02 , ....) way.
440 *
441 * 2) When you compile these please do keep, a metatag on testcase as
442 * # build : native classes classes.redef
443 *
444 * 3) When you do build these classes are psysically located in build as.
445 *
446 * TESTBASE/bin/newclass0* directory.
447 * eg: for nks/jvmti/scenarios/hotswap/HS204/hs204t001 you should see
448 * TESTBASE/bin/newclass0* /nsk/hotswap/HS204/hs204t001/MyClass.class
449 *
450 */
451
nsk_jvmti_redefineClass(jvmtiEnv * jvmti,jclass classToRedefine,const char * fileName)452 int nsk_jvmti_redefineClass(jvmtiEnv * jvmti,
453 jclass classToRedefine,
454 const char * fileName) {
455 redefineAttempted = NSK_TRUE;
456 if (nsk_jvmti_findOptionValue(NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE) == NULL) {
457 nsk_printf("# error expected: %s \n", NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE);
458 nsk_printf("Hint :: missing java -agentlib:agentlib=%s=DirName, ($TESTBASE/bin) \n",
459 NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE);
460 return NSK_FALSE;
461 }
462 if (fileName == NULL) {
463 nsk_printf("# error file name expected did not found \n");
464 return NSK_FALSE;
465 }
466 {
467 char file [1024];
468 //= "DEFAULT";
469 sprintf(file,"%s/%s.class",
470 nsk_jvmti_findOptionValue(NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE),
471 fileName);
472 nsk_printf("# info :: File = %s \n",file);
473
474 {
475 FILE *bytecode;
476 unsigned char * classBytes;
477 jvmtiError error;
478 jint size;
479
480 bytecode = fopen(file, "rb");
481 error= JVMTI_ERROR_NONE;
482 if (bytecode == NULL) {
483 nsk_printf("# error **Agent::error opening file %s \n",file);
484 return NSK_FALSE;
485 }
486
487 nsk_printf("# info **Agent:: opening file %s \n",file);
488 fseek(bytecode, 0, SEEK_END);
489 size = ftell(bytecode);
490 nsk_printf("# info file size= %ld\n",ftell(bytecode));
491 rewind(bytecode);
492 error = jvmti->Allocate(size,&classBytes);
493 if (error != JVMTI_ERROR_NONE) {
494 nsk_printf(" Failed to create memory %s \n",TranslateError(error));
495 return NSK_FALSE;
496 }
497
498 if (((jint) fread(classBytes, 1,size,bytecode)) != size) {
499 nsk_printf(" # error failed to read all the bytes , could be less or more \n");
500 return NSK_FALSE;
501 } else {
502 nsk_printf(" File red completely \n");
503 }
504 fclose(bytecode);
505 {
506 jvmtiClassDefinition classDef;
507 classDef.klass = classToRedefine;
508 classDef.class_byte_count= size;
509 classDef.class_bytes = classBytes;
510 error = jvmti->RedefineClasses(1,&classDef);
511 if (error != JVMTI_ERROR_NONE) {
512 nsk_printf("# error occured while redefining %s ",
513 TranslateError(error));
514 return NSK_FALSE;
515 }
516 }
517 }
518 }
519 redefineSucceed= NSK_TRUE;
520 return NSK_TRUE;
521 }
522
523 JNIEXPORT jboolean JNICALL
Java_nsk_share_jvmti_RedefineAgent_redefineAttempted(JNIEnv * jni,jobject obj)524 Java_nsk_share_jvmti_RedefineAgent_redefineAttempted(JNIEnv *jni, jobject obj) {
525
526 if (redefineAttempted) {
527 return JNI_TRUE;
528 }else {
529 return JNI_FALSE;
530 }
531 }
532
533
534 JNIEXPORT jboolean JNICALL
Java_nsk_share_jvmti_RedefineAgent_isRedefined(JNIEnv * jni,jobject obj)535 Java_nsk_share_jvmti_RedefineAgent_isRedefined(JNIEnv * jni, jobject obj) {
536
537 if (redefineSucceed) {
538 return JNI_TRUE;
539 }else {
540 return JNI_FALSE;
541 }
542 }
543 /**
544 * This jni method is a Java wrapper for agent status.
545 */
546 JNIEXPORT jboolean JNICALL
Java_nsk_share_jvmti_RedefineAgent_agentStatus(JNIEnv * jni,jobject obj)547 Java_nsk_share_jvmti_RedefineAgent_agentStatus(JNIEnv * jni, jobject obj) {
548 if (agentFailed) {
549 return JNI_FALSE;
550 } else {
551 return JNI_TRUE;
552 }
553 }
554
nsk_jvmti_getFileName(int redefineCnt,const char * dir,char * buf,size_t bufsize)555 void nsk_jvmti_getFileName(int redefineCnt, const char * dir, char * buf, size_t bufsize) {
556 snprintf(buf, bufsize, PATH_FORMAT, DIR_NAME, redefineCnt, dir);
557 buf[bufsize-1] = '\0';
558 }
559
nsk_jvmti_enableNotification(jvmtiEnv * jvmti,jvmtiEvent event,jthread thread)560 int nsk_jvmti_enableNotification(jvmtiEnv *jvmti,jvmtiEvent event, jthread thread) {
561 jvmtiError rc=JVMTI_ERROR_NONE;
562 rc = jvmti->SetEventNotificationMode(JVMTI_ENABLE, event, thread);
563 if (rc != JVMTI_ERROR_NONE) {
564 nsk_printf("# error Failed to set Notification for Event \n ");
565 return NSK_FALSE;
566 }
567 return NSK_TRUE;
568 }
569
nsk_jvmti_disableNotification(jvmtiEnv * jvmti,jvmtiEvent event,jthread thread)570 int nsk_jvmti_disableNotification(jvmtiEnv *jvmti,jvmtiEvent event, jthread thread) {
571 jvmtiError rc=JVMTI_ERROR_NONE;
572 rc = jvmti->SetEventNotificationMode(JVMTI_DISABLE, event, thread);
573 if (rc != JVMTI_ERROR_NONE) {
574 nsk_printf(" Failed to disaable Notification for Event ");
575 return NSK_FALSE;
576 }
577 return NSK_TRUE;
578 }
579
nsk_jvmti_agentFailed()580 void nsk_jvmti_agentFailed() {
581 agentFailed = NSK_TRUE;
582 }
583
isThreadExpected(jvmtiEnv * jvmti,jthread thread)584 int isThreadExpected(jvmtiEnv *jvmti, jthread thread) {
585 static const char *vm_jfr_buffer_thread_name = "VM JFR Buffer Thread";
586 static const char *jfr_request_timer_thread_name = "JFR request timer";
587 static const char *graal_management_bean_registration_thread_name =
588 "HotSpotGraalManagement Bean Registration";
589 static const char *graal_compiler_thread_name_prefix = "JVMCI CompilerThread";
590 static const size_t prefixLength = strlen(graal_compiler_thread_name_prefix);
591
592 jvmtiThreadInfo threadinfo;
593 NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(thread, &threadinfo));
594
595 if (strcmp(threadinfo.name, vm_jfr_buffer_thread_name) == 0)
596 return 0;
597
598 if (strcmp(threadinfo.name, jfr_request_timer_thread_name) == 0)
599 return 0;
600
601 if (strcmp(threadinfo.name, graal_management_bean_registration_thread_name) == 0)
602 return 0;
603
604 if ((strlen(threadinfo.name) > prefixLength) &&
605 strncmp(threadinfo.name, graal_compiler_thread_name_prefix, prefixLength) == 0)
606 return 0;
607
608 return 1;
609 }
610
611 #define SLEEP_DELAY 10L
612
suspendThreadAtMethod(jvmtiEnv * jvmti,jclass cls,jobject thread,jmethodID testMethod)613 int suspendThreadAtMethod(jvmtiEnv *jvmti, jclass cls, jobject thread, jmethodID testMethod) {
614 printf(">>>>>>>> Invoke SuspendThread()\n");
615
616 jvmtiError err = jvmti->SuspendThread(thread);
617 if (err != JVMTI_ERROR_NONE) {
618 printf("%s: Failed to call SuspendThread(): error=%d: %s\n",
619 __FILE__, err, TranslateError(err));
620 return NSK_FALSE;
621 }
622
623 int result = NSK_TRUE;
624 jmethodID method = NULL;
625 jlocation loc;
626
627 // We need to ensure that the thread is suspended at the right place when the top
628 // frame belongs to the test rather than to incidental Java code (classloading,
629 // JVMCI, etc). Below we do resume/suspend in the loop until the target method
630 // is executed in the top frame or the loop counter exceeds the limit.
631 for (int i = 0; i < 10; i++) {
632 err = jvmti->GetFrameLocation(thread, 0, &method, &loc);
633 if (err != JVMTI_ERROR_NONE) {
634 printf("(GetFrameLocation) unexpected error: %s (%d)\n",
635 TranslateError(err), err);
636 result = NSK_FALSE;
637 break;
638 }
639
640 char *name, *sig, *generic;
641 jvmti->GetMethodName(method, &name, &sig, &generic);
642 printf(">>> Attempt %d to suspend the thread. Top frame: \"%s%s\"\n",
643 i, name, sig);
644 if (method == testMethod) break;
645
646 err = jvmti->ResumeThread(thread);
647 if (err != JVMTI_ERROR_NONE) {
648 printf("(ResumeThread) unexpected error: %s (%d)\n",
649 TranslateError(err), err);
650 result = NSK_FALSE;
651 }
652
653 mssleep(SLEEP_DELAY);
654
655 err = jvmti->SuspendThread(thread);
656 if (err != JVMTI_ERROR_NONE) {
657 printf("(SuspendThread) unexpected error: %s (%d)\n",
658 TranslateError(err), err);
659 result = NSK_FALSE;
660 }
661 }
662 if(method == testMethod) {
663 printf("<<<<<<<< SuspendThread() is successfully done\n");
664 } else {
665 char *name, *sig, *generic;
666 jvmti->GetMethodName(testMethod, &name, &sig, &generic);
667 printf("Failed in the suspendThread: was not able to suspend thread "
668 "with required method \"%s%s\" on the top\n", name, sig);
669 result = NSK_FALSE;
670 }
671 return result;
672 }
673
createRawMonitor(jvmtiEnv * env,const char * name,jrawMonitorID * monitor)674 jint createRawMonitor(jvmtiEnv *env, const char *name, jrawMonitorID *monitor) {
675 jvmtiError error = env->CreateRawMonitor(name, monitor);
676 if (!NSK_JVMTI_VERIFY(error)) {
677 return JNI_ERR;
678 }
679 return JNI_OK;
680 }
681
exitOnError(jvmtiError error)682 void exitOnError(jvmtiError error) {
683 if (!NSK_JVMTI_VERIFY(error)) {
684 exit(error);
685 }
686 }
687
rawMonitorEnter(jvmtiEnv * env,jrawMonitorID monitor)688 void rawMonitorEnter(jvmtiEnv *env, jrawMonitorID monitor) {
689 jvmtiError error = env->RawMonitorEnter(monitor);
690 exitOnError(error);
691 }
692
rawMonitorExit(jvmtiEnv * env,jrawMonitorID monitor)693 void rawMonitorExit(jvmtiEnv *env, jrawMonitorID monitor) {
694 jvmtiError error = env->RawMonitorExit(monitor);
695 exitOnError(error);
696 }
697
rawMonitorNotify(jvmtiEnv * env,jrawMonitorID monitor)698 void rawMonitorNotify(jvmtiEnv *env, jrawMonitorID monitor) {
699 jvmtiError error = env->RawMonitorNotify(monitor);
700 exitOnError(error);
701 }
702
rawMonitorWait(jvmtiEnv * env,jrawMonitorID monitor,jlong millis)703 void rawMonitorWait(jvmtiEnv *env, jrawMonitorID monitor, jlong millis) {
704 jvmtiError error = env->RawMonitorWait(monitor, millis);
705 exitOnError(error);
706 }
707
getPhase(jvmtiEnv * env,jvmtiPhase * phase)708 void getPhase(jvmtiEnv *env, jvmtiPhase *phase) {
709 jvmtiError error = env->GetPhase(phase);
710 exitOnError(error);
711 }
712
713 /*************************************************************/
714
715 }
716