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