1 /*
   2  * Copyright (c) 2004, 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 <string.h>
  25 #include "jvmti.h"
  26 #include "agent_common.h"
  27 #include "jni_tools.h"
  28 #include "jvmti_tools.h"
  29 
  30 extern "C" {
  31 
  32 /* ============================================================================= */
  33 
  34 /* scaffold objects */
  35 static JNIEnv* jni = NULL;
  36 static jvmtiEnv *jvmti = NULL;
  37 static jlong timeout = 0;
  38 
  39 /* constant names */
  40 #define EXPECTED_CLASS_NAME "nsk/jvmti/scenarios/hotswap/HS201/hs201t002a"
  41 #define EXPECTED_CLASS_SIGN "Lnsk/jvmti/scenarios/hotswap/HS201/hs201t002a;"
  42 #define METHOD_NAME "doInit"
  43 #define METHOD_SIG "()V"
  44 #define LOCAL_VARIABLE_NAME "localVariable"
  45 #define PATH_TO_NEW_BYTECODE "pathToNewByteCode"
  46 
  47 static jint testStep;
  48 static int redefineNumber;
  49 static jint newClassSize;
  50 static unsigned char* newClassBytes;
  51 static jthread testedThread;
  52 static jclass testClass;
  53 char chbuffer[255];
  54 
  55 const char* getThreadName(JNIEnv* jni_env, jthread thread);
  56 const char* getClassName(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jobject object);
  57 int readNewBytecode(jvmtiEnv* jvmti);
  58 int getLocalVariableValue(jvmtiEnv *jvmti_env, jthread thread, jmethodID method);
  59 
  60 /* ============================================================================= */
  61 
  62 void setCurrentStep(JNIEnv* jni_env, int value) {
  63 
  64     jfieldID fld;
  65 
  66     if (!NSK_JNI_VERIFY(jni_env, (fld =
  67             NSK_CPP_STUB4(GetStaticFieldID, jni_env, testClass, "currentStep", "I")) != NULL)) {
  68         NSK_CPP_STUB2(FatalError, jni_env,
  69             "TEST FAILED: while getting currentStep fieldID\n");
  70     }
  71 
  72     if (!NSK_JNI_VERIFY_VOID(jni_env,
  73             NSK_CPP_STUB4(SetStaticIntField, jni_env, testClass, fld, value))) {
  74         NSK_CPP_STUB2(FatalError, jni_env,
  75             "TEST FAILED: while setting  value of currentStep fieldID\n");
  76     }
  77 
  78 }
  79 
  80 /* ============================================================================= */
  81 
  82 void enableEvent(jvmtiEnv *jvmti_env, jvmtiEvent event, jthread thread) {
  83 
  84     if (!NSK_JVMTI_VERIFY(
  85             NSK_CPP_STUB4(SetEventNotificationMode, jvmti_env, JVMTI_ENABLE,
  86                                             event, thread))) {
  87         NSK_COMPLAIN1("TEST FAILED: enabling %s\n", TranslateEvent(event));
  88         nsk_jvmti_setFailStatus();
  89     }
  90 }
  91 
  92 /* ============================================================================= */
  93 
  94 void disableEvent(jvmtiEnv *jvmti_env, jvmtiEvent event, jthread thread) {
  95 
  96     if (!NSK_JVMTI_VERIFY(
  97             NSK_CPP_STUB4(SetEventNotificationMode, jvmti_env, JVMTI_DISABLE,
  98                                             event, thread))) {
  99         NSK_COMPLAIN1("TEST FAILED: disabling %s\n", TranslateEvent(event));
 100         nsk_jvmti_setFailStatus();
 101     }
 102 }
 103 
 104 /* ============================================================================= */
 105 
 106 void redefineClass(jvmtiEnv *jvmti_env, jclass klass) {
 107 
 108     jvmtiClassDefinition classDef;
 109 
 110     char *className;
 111 
 112     if (!NSK_JVMTI_VERIFY(
 113             NSK_CPP_STUB4(GetClassSignature, jvmti_env, klass,
 114                                 &className, NULL))) {
 115         nsk_jvmti_setFailStatus();
 116         return;
 117     }
 118 
 119     if (!NSK_VERIFY(readNewBytecode(jvmti_env))) {
 120         NSK_COMPLAIN0("TEST FAILED: new bytecode could not be read\n");
 121         nsk_jvmti_setFailStatus();
 122         return;
 123     }
 124 
 125     classDef.klass = klass;
 126     classDef.class_byte_count = newClassSize;
 127     classDef.class_bytes = newClassBytes;
 128 
 129     NSK_DISPLAY1("\tredefining class %s\n", className);
 130     if (!NSK_JVMTI_VERIFY(
 131             NSK_CPP_STUB3(RedefineClasses, jvmti_env, 1, &classDef))) {
 132         NSK_COMPLAIN1("TEST FAILED: while redefining class %s\n", className);
 133         nsk_jvmti_setFailStatus();
 134         return;
 135     }
 136 
 137     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
 138             jvmti_env, (unsigned char*)className))) {
 139         nsk_jvmti_setFailStatus();
 140     }
 141 
 142 }
 143 
 144 /* ============================================================================= */
 145 
 146 /** Agent algorithm. */
 147 static void JNICALL
 148 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
 149 
 150     redefineNumber = 1;
 151     jni = agentJNI;
 152 
 153     NSK_DISPLAY0("Waiting for debuggee to become ready\n");
 154     if (!nsk_jvmti_waitForSync(timeout))
 155         return;
 156 
 157     testStep = 1;
 158     NSK_DISPLAY0("\n\n>>>> Debugge started, waiting for class loading \n");
 159     if (!nsk_jvmti_resumeSync())
 160         return;
 161 
 162     NSK_DISPLAY0("Waiting for debuggee's threads to finish\n");
 163     if (!nsk_jvmti_waitForSync(timeout))
 164         return;
 165 
 166     NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, testClass));
 167     NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, testedThread));
 168 
 169     NSK_DISPLAY0("Let debuggee to finish\n");
 170     if (!nsk_jvmti_resumeSync())
 171         return;
 172 }
 173 
 174 /* ============================================================================= */
 175 
 176 void setBreakPoint(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jclass klass) {
 177     jmethodID mid;
 178 
 179     if (!NSK_JNI_VERIFY(jni_env, (mid = NSK_CPP_STUB4(GetMethodID,
 180             jni_env, klass, METHOD_NAME, METHOD_SIG)) != NULL))
 181         NSK_CPP_STUB2(FatalError, jni_env,
 182             "[agent] failed to get ID for the java method\n");
 183 
 184     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetBreakpoint,
 185             jvmti_env, mid, 1)))
 186         NSK_CPP_STUB2(FatalError, jni_env,
 187             "[agent] failed to set breakpoint\n");
 188 }
 189 
 190 /* ============================================================================= */
 191 
 192 /**
 193  * CLASS_LOAD callback.
 194  *   -
 195  */
 196 JNIEXPORT void JNICALL
 197 callbackClassLoad(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 198                         jclass klass) {
 199 
 200     char *className;
 201     char *generic;
 202 
 203     if (!NSK_JVMTI_VERIFY(
 204             NSK_CPP_STUB4(GetClassSignature, jvmti_env, klass,
 205                                 &className, &generic))) {
 206         nsk_jvmti_setFailStatus();
 207         return;
 208     }
 209 
 210     if (strcmp(className, EXPECTED_CLASS_SIGN)
 211                         == 0) {
 212 
 213         NSK_DISPLAY1("\n\n>>>> Class loaded: %s", className);
 214         NSK_DISPLAY0(", activating breakpoint\n");
 215         setBreakPoint(jvmti_env, jni_env, klass);
 216     }
 217 
 218     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
 219             jvmti_env, (unsigned char*)className))) {
 220         nsk_jvmti_setFailStatus();
 221     }
 222 
 223     if (generic != NULL)
 224         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
 225                 jvmti_env, (unsigned char*)generic))) {
 226             nsk_jvmti_setFailStatus();
 227         }
 228 }
 229 
 230 /* ============================================================================= */
 231 
 232 /**
 233  * BREAKPOINT callback.
 234  *   -
 235  */
 236 JNIEXPORT void JNICALL
 237 callbackBreakpoint(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 238                          jmethodID method, jlocation location) {
 239 
 240     NSK_DISPLAY0("\n\n>>>>Breakpoint fired, enabling SINGLE_STEP\n");
 241     enableEvent(jvmti_env, JVMTI_EVENT_SINGLE_STEP, thread);
 242 }
 243 
 244 /* ============================================================================= */
 245 
 246 /**
 247  * BREAKPOINT callback.
 248  *   -
 249  */
 250 JNIEXPORT void JNICALL
 251 callbackSingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 252                             jmethodID method, jlocation location) {
 253 
 254     char *methodName;
 255 
 256     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB5(GetMethodName,
 257             jvmti_env, method, &methodName, NULL, NULL))) {
 258         NSK_COMPLAIN0("TEST FAILED: unable to get method name during Breakpoint callback\n\n");
 259     }
 260 
 261     if (strcmp(methodName, METHOD_NAME) == 0) {
 262         char *declaringClassName;
 263         jclass declaringClass;
 264 
 265         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetMethodDeclaringClass,
 266                 jvmti_env, method, &declaringClass))) {
 267             NSK_COMPLAIN0("TEST FAILED: unable to get method name during Breakpoint callback\n\n");
 268         }
 269 
 270         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature,
 271                 jvmti_env, declaringClass, &declaringClassName, NULL))) {
 272             NSK_COMPLAIN0("TEST FAILED: unable to get method name during Breakpoint callback\n\n");
 273         }
 274 
 275         if (strcmp(declaringClassName, EXPECTED_CLASS_SIGN) == 0) {
 276             int value;
 277             jboolean is_obsolete;
 278 
 279             /* getting local variable table*/
 280             value = getLocalVariableValue(jvmti_env, thread, method);
 281 
 282             switch (testStep) {
 283             case 1:
 284 
 285                 if (value == 1) {
 286                     redefineClass(jvmti_env, declaringClass);
 287                     testStep++;
 288                 }
 289                 break;
 290 
 291             case 2:
 292 
 293                 NSK_DISPLAY1("\n\n>>>> Checking if redefined method is not obsolete\n", testStep);
 294 
 295                 if (!NSK_JVMTI_VERIFY(
 296                             NSK_CPP_STUB3(IsMethodObsolete, jvmti, method, &is_obsolete))) {
 297                     NSK_COMPLAIN0("TEST FAILED: unable to check method to be obsolete\n");
 298                     nsk_jvmti_setFailStatus();
 299                     return;
 300                 }
 301 
 302                 if (is_obsolete) {
 303                     NSK_COMPLAIN0("TEST FAILED: method must not be obsolete\n");
 304                     nsk_jvmti_setFailStatus();
 305                 }
 306                 testStep++;
 307                 break;
 308 
 309             case 3:
 310 
 311                 NSK_DISPLAY1("\n\n>>>> Popping the currently executing frame\n", testStep);
 312                 testStep++;
 313                 setCurrentStep(jni_env, testStep);
 314 
 315                 break;
 316 
 317             case 5:
 318 
 319                 if (value < 10) {
 320                     NSK_DISPLAY1("\n\n>>>> Disabling single step\n", testStep);
 321                     disableEvent(jvmti_env, JVMTI_EVENT_SINGLE_STEP, thread);
 322                     setCurrentStep(jni_env, testStep);
 323                 }
 324 
 325             } /* case */
 326 
 327         }
 328 
 329         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
 330                 jvmti_env, (unsigned char*) declaringClassName))) {
 331             NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to method name\n\n");
 332         }
 333 
 334     }
 335 
 336     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
 337             jvmti_env, (unsigned char*) methodName))) {
 338         NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to method name\n\n");
 339     }
 340 
 341 }
 342 
 343 /* ============================================================================= */
 344 
 345 /**
 346  * EXCEPTION callback.
 347  *   -
 348  */
 349 JNIEXPORT void JNICALL
 350 callbackException(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 351                         jmethodID method, jlocation location, jobject exception,
 352                         jmethodID catch_method, jlocation catch_location) {
 353 
 354     const char *className;
 355 
 356     className = getClassName(jvmti_env, jni_env, exception);
 357 
 358     if (strcmp(EXPECTED_CLASS_SIGN, className) == 0) {
 359         jclass klass;
 360 
 361         NSK_DISPLAY2("\n\n>>>> Exception %s in thread - %s\n",
 362                         className, getThreadName(jni_env, thread));
 363 
 364         testStep++;
 365         if (!NSK_JNI_VERIFY(jni_env, (klass =
 366                 NSK_CPP_STUB2(GetObjectClass, jni_env, exception)) != NULL)) {
 367             nsk_jvmti_setFailStatus();
 368             return;
 369         }
 370 
 371         redefineClass(jvmti_env, klass);
 372     }
 373 }
 374 
 375 /* ============================================================================= */
 376 
 377 /**
 378  * EXCEPTION_CATCH callback.
 379  *   -
 380  */
 381 JNIEXPORT void JNICALL
 382 callbackExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
 383                         jmethodID method, jlocation location,
 384                         jobject exception) {
 385 
 386     const char *className;
 387 
 388     className = getClassName(jvmti_env, jni_env, exception);
 389 
 390     if (strcmp(EXPECTED_CLASS_SIGN, className) == 0) {
 391         jclass klass;
 392 
 393         NSK_DISPLAY2("\n\n>>>> Caught exception %s in thread - %s\n",
 394                         className, getThreadName(jni_env, thread));
 395 
 396         testStep++;
 397         if (!NSK_JNI_VERIFY(jni_env, (klass =
 398                 NSK_CPP_STUB2(GetObjectClass, jni_env, exception)) != NULL)) {
 399             nsk_jvmti_setFailStatus();
 400             return;
 401         }
 402 
 403         redefineClass(jvmti_env, klass);
 404     }
 405 }
 406 
 407 /* ============================================================================= */
 408 
 409 int readNewBytecode(jvmtiEnv* jvmti) {
 410 
 411     char filename[256];
 412     FILE *bytecode;
 413     const char *pathToByteCode = nsk_jvmti_findOptionValue(PATH_TO_NEW_BYTECODE);
 414     jint read_bytes;
 415 
 416 
 417     if (!pathToByteCode) {
 418         NSK_COMPLAIN0("TEST FAILED: error opening file\n");
 419         return NSK_FALSE;
 420     }
 421 
 422     sprintf(filename,"%s/%s/%s.class",
 423                 pathToByteCode, "newclass", EXPECTED_CLASS_NAME);
 424 
 425     NSK_DISPLAY1("\treading new bytecode for the tested class\n\tfile name: %s\n",
 426                         filename);
 427 
 428     bytecode = fopen(filename, "rb");
 429     if (bytecode == NULL) {
 430         NSK_COMPLAIN0("TEST FAILED: error opening file\n");
 431         return NSK_FALSE;
 432     }
 433 
 434     fseek(bytecode, 0, SEEK_END);
 435     newClassSize = ftell(bytecode);
 436     rewind(bytecode);
 437 
 438     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(Allocate, jvmti,
 439                                 newClassSize, &newClassBytes))) {
 440         NSK_COMPLAIN0("buffer couldn't be allocated\n");
 441         return NSK_FALSE;
 442     }
 443     read_bytes = (jint) fread(newClassBytes, 1, newClassSize, bytecode);
 444     fclose(bytecode);
 445     if (read_bytes != newClassSize) {
 446         NSK_COMPLAIN0("TEST FAILED: error reading file\n");
 447         return NSK_FALSE;
 448     }
 449 
 450     return NSK_TRUE;
 451 }
 452 
 453 /* ============================================================================= */
 454 
 455 const char* getThreadName(JNIEnv* jni_env, jthread thread) {
 456     jmethodID methodID;
 457     jclass klass;
 458     jstring jthreadName;
 459     const char *threadName;
 460 
 461     strcpy(chbuffer, "");
 462 
 463     if (!NSK_JNI_VERIFY(jni_env, (klass =
 464             NSK_CPP_STUB2(GetObjectClass, jni_env, thread)) != NULL)) {
 465         nsk_jvmti_setFailStatus();
 466         return chbuffer;
 467     }
 468 
 469     if (!NSK_JNI_VERIFY(jni_env, (methodID =
 470             NSK_CPP_STUB4(GetMethodID, jni_env, klass,
 471                         "getName", "()Ljava/lang/String;")) != NULL)) {
 472         nsk_jvmti_setFailStatus();
 473         return chbuffer;
 474     }
 475 
 476     jthreadName = (jstring) NSK_CPP_STUB3(CallObjectMethod, jni_env, thread,
 477                         methodID);
 478 
 479     threadName = NSK_CPP_STUB3(GetStringUTFChars, jni_env, jthreadName, 0);
 480 
 481     strcpy(chbuffer, threadName);
 482 
 483     NSK_CPP_STUB3(ReleaseStringUTFChars, jni_env, jthreadName, threadName);
 484 
 485     return chbuffer;
 486 }
 487 
 488 /* ============================================================================= */
 489 
 490 const char* getClassName(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jobject object) {
 491 
 492     char *className;
 493     char *generic;
 494     jclass klass;
 495 
 496     strcpy(chbuffer, "");
 497 
 498     if (!NSK_JNI_VERIFY(jni_env, (klass =
 499             NSK_CPP_STUB2(GetObjectClass, jni_env, object)) != NULL)) {
 500         nsk_jvmti_setFailStatus();
 501         return chbuffer;
 502     }
 503 
 504     if (!NSK_JVMTI_VERIFY(
 505             NSK_CPP_STUB4(GetClassSignature, jvmti_env, klass,
 506                                 &className, &generic))) {
 507         nsk_jvmti_setFailStatus();
 508         return chbuffer;
 509     }
 510 
 511     strcpy(chbuffer, className);
 512 
 513     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
 514             jvmti_env, (unsigned char*)className))) {
 515         nsk_jvmti_setFailStatus();
 516     }
 517 
 518     if (generic != NULL)
 519         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
 520                 jvmti_env, (unsigned char*)generic))) {
 521             nsk_jvmti_setFailStatus();
 522         }
 523 
 524     return chbuffer;
 525 }
 526 
 527 /* ============================================================================= */
 528 
 529 int getLocalVariableValue(jvmtiEnv *jvmti_env, jthread thread,
 530                                 jmethodID method) {
 531 
 532     jvmtiLocalVariableEntry *table = NULL;
 533     jint entryCount = 0;
 534     int i;
 535     jint value = -1;
 536 
 537     /* getting local variable table*/
 538     if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetLocalVariableTable,
 539             jvmti_env, method, &entryCount, &table))) {
 540         NSK_COMPLAIN0("TEST FAILED: unable to get local variable table\n\n");
 541     }
 542 
 543     if (table != NULL) {
 544         jvmtiError error;
 545 
 546         for (i = 0; i < entryCount; i++) {
 547             if (strcmp(table[i].name, LOCAL_VARIABLE_NAME) == 0) {
 548                 error = NSK_CPP_STUB5(GetLocalInt, jvmti_env, thread, 0,
 549                                         table[i].slot, &value);
 550                 if (!NSK_VERIFY(error == JVMTI_ERROR_NONE
 551                                 || error == JVMTI_ERROR_INVALID_SLOT))
 552                     NSK_COMPLAIN0("TEST FAILED: unable to get local variable table\n\n");
 553             }
 554         }
 555 
 556         for (i = 0; i < entryCount; i++) {
 557 
 558             if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
 559                     jvmti_env, (unsigned char*)table[i].name))) {
 560                 NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to method name\n\n");
 561             }
 562 
 563             if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
 564                     jvmti_env, (unsigned char*)table[i].signature))) {
 565                 NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to method signature\n\n");
 566             }
 567 
 568         }
 569 
 570         if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
 571                 jvmti_env, (unsigned char*)table))) {
 572             NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to local variable table\n\n");
 573         }
 574 
 575     }
 576 
 577     return value;
 578 }
 579 
 580 /* ============================================================================= */
 581 
 582 JNIEXPORT void JNICALL
 583 Java_nsk_jvmti_scenarios_hotswap_HS201_hs201t002_setThread(JNIEnv *env,
 584                         jclass cls, jthread thread) {
 585 
 586     if (!NSK_JNI_VERIFY(env, (testClass = (jclass)
 587             NSK_CPP_STUB2(NewGlobalRef, env, cls)) != NULL))
 588         nsk_jvmti_setFailStatus();
 589 
 590     if (!NSK_JNI_VERIFY(env, (testedThread =
 591             NSK_CPP_STUB2(NewGlobalRef, env, thread)) != NULL))
 592         nsk_jvmti_setFailStatus();
 593 
 594 }
 595 
 596 /* ============================================================================= */
 597 
 598 JNIEXPORT jboolean JNICALL
 599 Java_nsk_jvmti_scenarios_hotswap_HS201_hs201t002_resumeThread(JNIEnv *env,
 600                         jclass cls, jthread thread) {
 601 
 602     NSK_DISPLAY0("\tresuming thread...\n");
 603     disableEvent(jvmti, JVMTI_EVENT_SINGLE_STEP, thread);
 604 
 605     if (!NSK_JVMTI_VERIFY(
 606             NSK_CPP_STUB2(ResumeThread, jvmti, thread))) {
 607         NSK_COMPLAIN0("TEST FAILED: unable to resume the thread\n");
 608         nsk_jvmti_setFailStatus();
 609         return NSK_FALSE;
 610     }
 611 
 612     return NSK_TRUE;
 613 }
 614 
 615 /* ============================================================================= */
 616 
 617 JNIEXPORT jboolean JNICALL
 618 Java_nsk_jvmti_scenarios_hotswap_HS201_hs201t002_suspendThread(JNIEnv *env,
 619                         jclass cls, jthread thread) {
 620 
 621     NSK_DISPLAY0("\tsuspending thread...\n");
 622     disableEvent(jvmti, JVMTI_EVENT_SINGLE_STEP, thread);
 623 
 624     if (!NSK_JVMTI_VERIFY(
 625             NSK_CPP_STUB2(SuspendThread, jvmti, thread))) {
 626         NSK_COMPLAIN0("TEST FAILED: unable to suspend the thread\n");
 627         nsk_jvmti_setFailStatus();
 628         return NSK_FALSE;
 629     }
 630 
 631     return NSK_TRUE;
 632 }
 633 
 634 /* ============================================================================= */
 635 
 636 JNIEXPORT jboolean JNICALL
 637 Java_nsk_jvmti_scenarios_hotswap_HS201_hs201t002_popFrame(JNIEnv *env,
 638                         jclass cls, jthread thread) {
 639 
 640     NSK_DISPLAY0("\tpopping frame...\n");
 641     if (!NSK_JVMTI_VERIFY(
 642                 NSK_CPP_STUB2(PopFrame, jvmti, thread))) {
 643         NSK_COMPLAIN0("TEST FAILED: unable to pop the currently executed frame\n");
 644         nsk_jvmti_setFailStatus();
 645         return NSK_FALSE;
 646     }
 647 
 648     NSK_DISPLAY0("\tresuming thread...\n");
 649     if (!NSK_JVMTI_VERIFY(
 650             NSK_CPP_STUB2(ResumeThread, jvmti, thread))) {
 651         NSK_COMPLAIN0("TEST FAILED: unable to resume the thread\n");
 652         nsk_jvmti_setFailStatus();
 653         return NSK_FALSE;
 654     }
 655 
 656     testStep++;
 657     enableEvent(jvmti, JVMTI_EVENT_SINGLE_STEP, thread);
 658 
 659     return NSK_TRUE;
 660 }
 661 
 662 /* ============================================================================= */
 663 
 664 /** Agent library initialization. */
 665 #ifdef STATIC_BUILD
 666 JNIEXPORT jint JNICALL Agent_OnLoad_hs201t002(JavaVM *jvm, char *options, void *reserved) {
 667     return Agent_Initialize(jvm, options, reserved);
 668 }
 669 JNIEXPORT jint JNICALL Agent_OnAttach_hs201t002(JavaVM *jvm, char *options, void *reserved) {
 670     return Agent_Initialize(jvm, options, reserved);
 671 }
 672 JNIEXPORT jint JNI_OnLoad_hs201t002(JavaVM *jvm, char *options, void *reserved) {
 673     return JNI_VERSION_1_8;
 674 }
 675 #endif
 676 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 677 
 678     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 679         return JNI_ERR;
 680 
 681     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
 682 
 683     if (!NSK_VERIFY((jvmti =
 684             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
 685         return JNI_ERR;
 686 
 687     {
 688         jvmtiCapabilities caps;
 689         memset(&caps, 0, sizeof(caps));
 690 
 691         caps.can_generate_exception_events = 1;
 692         caps.can_generate_breakpoint_events = 1;
 693         caps.can_generate_single_step_events = 1;
 694         caps.can_access_local_variables = 1;
 695         caps.can_redefine_classes = 1;
 696         caps.can_pop_frame = 1;
 697         caps.can_suspend = 1;
 698 
 699         if (!NSK_JVMTI_VERIFY(
 700                 NSK_CPP_STUB2(AddCapabilities, jvmti, &caps)))
 701             return JNI_ERR;
 702     }
 703 
 704     {
 705         jvmtiEventCallbacks eventCallbacks;
 706         memset(&eventCallbacks, 0, sizeof(eventCallbacks));
 707         eventCallbacks.ClassLoad = callbackClassLoad;
 708         eventCallbacks.Exception = callbackException;
 709         eventCallbacks.ExceptionCatch = callbackExceptionCatch;
 710         eventCallbacks.Breakpoint = callbackBreakpoint;
 711         eventCallbacks.SingleStep = callbackSingleStep;
 712         if (!NSK_JVMTI_VERIFY(
 713                 NSK_CPP_STUB3(SetEventCallbacks, jvmti,
 714                                     &eventCallbacks, sizeof(eventCallbacks))))
 715             return JNI_ERR;
 716     }
 717 
 718     NSK_DISPLAY0("Enable events\n");
 719 
 720     enableEvent(jvmti, JVMTI_EVENT_CLASS_LOAD, testedThread);
 721     enableEvent(jvmti, JVMTI_EVENT_BREAKPOINT, testedThread);
 722     enableEvent(jvmti, JVMTI_EVENT_EXCEPTION, testedThread);
 723     enableEvent(jvmti, JVMTI_EVENT_EXCEPTION_CATCH, testedThread);
 724 
 725     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
 726         return JNI_ERR;
 727 
 728     return JNI_OK;
 729 }
 730 
 731 /* ============================================================================= */
 732 
 733 }