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 #include "JVMTITools.h"
  30 
  31 extern "C" {
  32 
  33 /* ============================================================================= */
  34 
  35 /* scaffold objects */
  36 static JNIEnv* jni = NULL;
  37 static jvmtiEnv *jvmti = NULL;
  38 static jlong timeout = 0;
  39 static jrawMonitorID syncLock = NULL;
  40 
  41 /* constant names */
  42 #define JVMTI_EVENT_COUNT   (int)(JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL + 1)
  43 #define EXPECTED_CLASS_NAME "Lnsk/jvmti/scenarios/events/EM01/em01t002a;"
  44 #define CLASS_LOADER_COUNT_PARAM "classLoaderCount"
  45 
  46 static int eventCount[JVMTI_EVENT_COUNT];
  47 
  48 static int classLoaderCount = 0;
  49 
  50 static jvmtiPhase currentPhase;
  51 
  52 /* ============================================================================= */
  53 /* ============================================================================= */
  54 
  55 
  56 /*
  57  * Class:     nsk_jvmti_scenarios_events_EM01_em01t002
  58  * Method:    loadClass
  59  * Signature: (Lnsk/share/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
  60  */
  61 JNIEXPORT jclass JNICALL
  62 Java_nsk_jvmti_scenarios_events_EM01_em01t002_loadClass(JNIEnv *jni_env,
  63                         jobject o, jobject loader, jstring className) {
  64     jclass klass;
  65     jmethodID methodID;
  66     jclass loadedClass;
  67 
  68     klass = jni_env->GetObjectClass(loader);
  69     if (!NSK_JNI_VERIFY(jni_env, klass != NULL)) {
  70         nsk_jvmti_setFailStatus();
  71         return NULL;
  72     }
  73 
  74     methodID = jni_env->GetMethodID(
  75                 klass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
  76     if (!NSK_JNI_VERIFY(jni_env, methodID != NULL)) {
  77         nsk_jvmti_setFailStatus();
  78         return NULL;
  79     }
  80 
  81     loadedClass = (jclass) jni_env->CallObjectMethod(loader, methodID, className);
  82     if (!NSK_JNI_VERIFY(jni_env, loadedClass != NULL)) {
  83         nsk_jvmti_setFailStatus();
  84         return NULL;
  85     }
  86 
  87     return loadedClass;
  88 }
  89 
  90 /*
  91  * Class:     nsk_jvmti_scenarios_events_EM01_em01t002
  92  * Method:    prepareClass
  93  * Signature: (Ljava/lang/Class;)Z
  94  */
  95 JNIEXPORT jboolean JNICALL
  96 Java_nsk_jvmti_scenarios_events_EM01_em01t002_prepareClass(JNIEnv *jni_env,
  97                         jobject o, jclass klass) {
  98     jfieldID fieldID;
  99 
 100     fieldID = jni_env->GetStaticFieldID(klass, "toProvokePreparation", "I");
 101     if (!NSK_JNI_VERIFY(jni_env, fieldID != NULL)) {
 102         nsk_jvmti_setFailStatus();
 103         return NSK_FALSE;
 104     }
 105 
 106     return NSK_TRUE;
 107 }
 108 
 109 /*
 110  * Class:     nsk_jvmti_scenarios_events_EM01_em01t002
 111  * Method:    startThread
 112  * Signature: (Ljava/lang/Thread;)Z
 113  */
 114 JNIEXPORT jboolean JNICALL
 115 Java_nsk_jvmti_scenarios_events_EM01_em01t002_startThread(JNIEnv *jni_env,
 116                         jobject o, jobject thread) {
 117     jclass klass;
 118     jmethodID methodID;
 119 
 120     klass = jni_env->GetObjectClass(thread);
 121     if (!NSK_JNI_VERIFY(jni_env, klass != NULL)) {
 122         nsk_jvmti_setFailStatus();
 123         return NSK_FALSE;
 124     }
 125 
 126     methodID = jni_env->GetMethodID(klass, "start", "()V");
 127     if (!NSK_JNI_VERIFY(jni_env, methodID != NULL)) {
 128         nsk_jvmti_setFailStatus();
 129         return NSK_FALSE;
 130     }
 131 
 132     if (!NSK_JNI_VERIFY_VOID(jni_env,jni_env->CallVoidMethod(thread, methodID)) ) {
 133         nsk_jvmti_setFailStatus();
 134         return NSK_FALSE;
 135     }
 136 
 137     return NSK_TRUE;
 138 }
 139 
 140 /* ============================================================================= */
 141 /* ============================================================================= */
 142 
 143 static void
 144 changeCount(jvmtiEvent event) {
 145 
 146     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(syncLock)))
 147         nsk_jvmti_setFailStatus();
 148 
 149     eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL]++;
 150 
 151     if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(syncLock)))
 152         nsk_jvmti_setFailStatus();
 153 
 154 }
 155 
 156 /* ============================================================================= */
 157 
 158 static void
 159 showEventStatistics() {
 160     int i;
 161     const char* str;
 162 
 163     NSK_DISPLAY0("Event statistics\n");
 164     NSK_DISPLAY0("----------------\n");
 165     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
 166         if (eventCount[i] > 0) {
 167             str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL));
 168             NSK_DISPLAY2("%-40s %7d\n", str, eventCount[i]);
 169         }
 170     }
 171 }
 172 
 173 /* ========================================================================== */
 174 
 175 /* callbacks */
 176 void
 177 classEventsHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env,
 178                             jclass klass) {
 179 
 180     char *className;
 181     char *generic;
 182     jvmtiPhase phase;
 183 
 184     if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &className, &generic))) {
 185         nsk_jvmti_setFailStatus();
 186         return;
 187     }
 188 
 189     if (strcmp(className, EXPECTED_CLASS_NAME) == 0) {
 190         changeCount(event);
 191         NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n",
 192                             TranslateEvent(event),
 193                             eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL],
 194                             className);
 195     }
 196 
 197     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
 198         nsk_jvmti_setFailStatus();
 199     }
 200 
 201     if (phase != currentPhase) {
 202         NSK_DISPLAY2("Unexpected phase %s, but supposed %s",
 203                 TranslatePhase(phase), TranslatePhase(currentPhase));
 204     }
 205 
 206     if ((phase != JVMTI_PHASE_LIVE) && (phase != JVMTI_PHASE_START)) {
 207         NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n",
 208                     TranslateEvent(event),
 209                     TranslatePhase(phase),
 210                     phase,
 211                     className);
 212         nsk_jvmti_setFailStatus();
 213     }
 214 
 215     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) {
 216         nsk_jvmti_setFailStatus();
 217     }
 218     if (generic != NULL)
 219         if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) {
 220             nsk_jvmti_setFailStatus();
 221         }
 222 }
 223 
 224 void
 225 threadEventHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env,
 226                             jthread thread) {
 227     jclass classObject;
 228     char *className;
 229     char *generic;
 230     jvmtiPhase phase;
 231 
 232 
 233     classObject = jni_env->GetObjectClass(thread);
 234     if (!NSK_JNI_VERIFY(jni_env, classObject != NULL)) {
 235         nsk_jvmti_setFailStatus();
 236         return;
 237     }
 238 
 239     if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(classObject, &className, &generic))) {
 240         nsk_jvmti_setFailStatus();
 241         return;
 242     }
 243 
 244     if (strcmp(className, EXPECTED_CLASS_NAME) == 0) {
 245         changeCount(event);
 246         NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n",
 247                             TranslateEvent(event),
 248                             eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL],
 249                             className);
 250     }
 251 
 252     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
 253         nsk_jvmti_setFailStatus();
 254     }
 255 
 256     if (phase != currentPhase) {
 257         NSK_DISPLAY2("Unexpected phase %s, but supposed %s",
 258                 TranslatePhase(phase), TranslatePhase(currentPhase));
 259     }
 260 
 261     if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) {
 262         NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n",
 263                     TranslateEvent(event),
 264                     TranslatePhase(phase),
 265                     phase,
 266                     className);
 267         nsk_jvmti_setFailStatus();
 268     }
 269 
 270     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) {
 271         nsk_jvmti_setFailStatus();
 272     }
 273     if (generic != NULL)
 274         if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) {
 275             nsk_jvmti_setFailStatus();
 276         }
 277 }
 278 
 279 JNIEXPORT void JNICALL
 280 cbVMStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env) {
 281 
 282     jvmtiPhase phase;
 283 
 284     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
 285         nsk_jvmti_setFailStatus();
 286     }
 287 
 288     if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) {
 289         NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
 290                     TranslateEvent(JVMTI_EVENT_VM_START),
 291                     TranslatePhase(phase),
 292                     phase);
 293         nsk_jvmti_setFailStatus();
 294     }
 295 
 296     changeCount(JVMTI_EVENT_VM_START);
 297     currentPhase = JVMTI_PHASE_START;
 298 }
 299 
 300 JNIEXPORT void JNICALL
 301 cbVMInit(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
 302 
 303     jvmtiPhase phase;
 304 
 305     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
 306         nsk_jvmti_setFailStatus();
 307     }
 308 
 309     if (phase != JVMTI_PHASE_LIVE) {
 310         NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
 311                     TranslateEvent(JVMTI_EVENT_VM_INIT),
 312                     TranslatePhase(phase),
 313                     phase);
 314         nsk_jvmti_setFailStatus();
 315     }
 316 
 317     changeCount(JVMTI_EVENT_VM_INIT);
 318     currentPhase = JVMTI_PHASE_LIVE;
 319 }
 320 
 321 JNIEXPORT void JNICALL
 322 cbVMDeath(jvmtiEnv* jvmti_env, JNIEnv* jni_env) {
 323 
 324     jvmtiPhase phase;
 325 
 326     if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
 327         nsk_jvmti_setFailStatus();
 328     }
 329 
 330     if (phase != JVMTI_PHASE_LIVE) {
 331         NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
 332                     TranslateEvent(JVMTI_EVENT_VM_INIT),
 333                     TranslatePhase(phase),
 334                     phase);
 335         nsk_jvmti_setFailStatus();
 336     }
 337 
 338     currentPhase = JVMTI_PHASE_DEAD;
 339     changeCount(JVMTI_EVENT_VM_DEATH);
 340 
 341     if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock)))
 342         nsk_jvmti_setFailStatus();
 343 
 344 }
 345 
 346 JNIEXPORT void JNICALL
 347 cbClassLoad(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread,
 348                     jclass klass) {
 349 
 350     classEventsHandler(JVMTI_EVENT_CLASS_LOAD, jvmti_env, jni_env, klass);
 351 }
 352 
 353 JNIEXPORT void JNICALL
 354 cbClassPrepare(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread,
 355                     jclass klass) {
 356 
 357     classEventsHandler(JVMTI_EVENT_CLASS_PREPARE, jvmti_env, jni_env, klass);
 358 }
 359 
 360 JNIEXPORT void JNICALL
 361 cbThreadStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
 362 
 363     threadEventHandler(JVMTI_EVENT_THREAD_START, jvmti_env, jni_env, thread);
 364 }
 365 
 366 JNIEXPORT void JNICALL
 367 cbThreadEnd(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
 368 
 369     threadEventHandler(JVMTI_EVENT_THREAD_END, jvmti_env, jni_env, thread);
 370 }
 371 
 372 /* ============================================================================= */
 373 
 374 static int
 375 enableEvent(jvmtiEventMode enable, jvmtiEvent event) {
 376 
 377     if (enable == JVMTI_ENABLE) {
 378         NSK_DISPLAY1("enabling %s\n", TranslateEvent(event));
 379     } else {
 380         NSK_DISPLAY1("disabling %s\n", TranslateEvent(event));
 381     }
 382 
 383 
 384     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(enable, event, NULL))) {
 385         nsk_jvmti_setFailStatus();
 386         return NSK_FALSE;
 387     }
 388 
 389     return NSK_TRUE;
 390 }
 391 
 392 /* ============================================================================= */
 393 
 394 /**
 395  * Testcase: check tested events.
 396  *   - check if expected events received for each method
 397  *
 398  * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break.
 399  */
 400 int checkEvents(int step) {
 401 
 402     int i;
 403     jvmtiEvent curr;
 404     int result = NSK_TRUE;
 405     int mustBeChecked;
 406 
 407     showEventStatistics();
 408 
 409     for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
 410 
 411         curr = (jvmtiEvent) (i + JVMTI_MIN_EVENT_TYPE_VAL);
 412         switch (step) {
 413         case 1:
 414             mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD)
 415                     || (curr == JVMTI_EVENT_CLASS_PREPARE));
 416             break;
 417 
 418         case 2:
 419             mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD)
 420                     || (curr == JVMTI_EVENT_CLASS_PREPARE)
 421                     || (curr == JVMTI_EVENT_THREAD_START)
 422                     || (curr == JVMTI_EVENT_THREAD_END));
 423             break;
 424         default:
 425             mustBeChecked = NSK_TRUE;
 426         }
 427 
 428         if (mustBeChecked && eventCount[i] != classLoaderCount) {
 429                 nsk_jvmti_setFailStatus();
 430                 NSK_COMPLAIN3("Unexpected number of %s events %7d\n\texpected value %d\n",
 431                                     TranslateEvent(curr),
 432                                     eventCount[i],
 433                                     classLoaderCount);
 434                 nsk_jvmti_setFailStatus();
 435                 result = NSK_FALSE;
 436         }
 437     }
 438 
 439     return result;
 440 }
 441 
 442 /* ============================================================================= */
 443 
 444 static int
 445 setCallBacks() {
 446     jvmtiEventCallbacks eventCallbacks;
 447     memset(&eventCallbacks, 0, sizeof(eventCallbacks));
 448 
 449     eventCallbacks.VMStart      = cbVMStart;
 450     eventCallbacks.VMInit       = cbVMInit;
 451     eventCallbacks.VMDeath      = cbVMDeath;
 452     eventCallbacks.ClassLoad    = cbClassLoad;
 453     eventCallbacks.ClassPrepare = cbClassPrepare;
 454     eventCallbacks.ThreadStart  = cbThreadStart;
 455     eventCallbacks.ThreadEnd    = cbThreadEnd;
 456 
 457     if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks))))
 458         return NSK_FALSE;
 459 
 460     return NSK_TRUE;
 461 }
 462 
 463 /* ============================================================================= */
 464 
 465 /** Agent algorithm. */
 466 static void JNICALL
 467 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
 468 
 469     NSK_DISPLAY0("Wait for debuggee to become ready\n");
 470     if (!nsk_jvmti_waitForSync(timeout))
 471         return;
 472 
 473     NSK_DISPLAY0("Let debuggee to load class\n");
 474     if (!nsk_jvmti_resumeSync())
 475         return;
 476 
 477     if (!nsk_jvmti_waitForSync(timeout))
 478         return;
 479 
 480     /* check only CLASS_LOAD and CLASS_PREPARE events */
 481     if (!checkEvents(1)) {
 482         nsk_jvmti_setFailStatus();
 483     }
 484 
 485     NSK_DISPLAY0("Let debuggee to start threads\n");
 486     if (!nsk_jvmti_resumeSync())
 487         return;
 488 
 489     if (!nsk_jvmti_waitForSync(timeout))
 490         return;
 491 
 492     NSK_DISPLAY0("check event 2\n");
 493     if (!checkEvents(2)) {
 494         nsk_jvmti_setFailStatus();
 495     }
 496 
 497     NSK_DISPLAY0("Let debuggee to finish\n");
 498     if (!nsk_jvmti_resumeSync())
 499         return;
 500 
 501 }
 502 
 503 /* ============================================================================= */
 504 
 505 /** Agent library initialization. */
 506 #ifdef STATIC_BUILD
 507 JNIEXPORT jint JNICALL Agent_OnLoad_em01t002(JavaVM *jvm, char *options, void *reserved) {
 508     return Agent_Initialize(jvm, options, reserved);
 509 }
 510 JNIEXPORT jint JNICALL Agent_OnAttach_em01t002(JavaVM *jvm, char *options, void *reserved) {
 511     return Agent_Initialize(jvm, options, reserved);
 512 }
 513 JNIEXPORT jint JNI_OnLoad_em01t002(JavaVM *jvm, char *options, void *reserved) {
 514     return JNI_VERSION_1_8;
 515 }
 516 #endif
 517 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 518 
 519     currentPhase = JVMTI_PHASE_ONLOAD;
 520 
 521     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 522         return JNI_ERR;
 523 
 524     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
 525     classLoaderCount = nsk_jvmti_findOptionIntValue(CLASS_LOADER_COUNT_PARAM, 10);
 526 
 527     jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved);
 528     if (!NSK_VERIFY(jvmti != NULL))
 529         return JNI_ERR;
 530 
 531     if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_syncLock", &syncLock))) {
 532         nsk_jvmti_setFailStatus();
 533         return JNI_ERR;
 534     }
 535 
 536     if (!setCallBacks()) {
 537         return JNI_ERR;
 538     }
 539 
 540     if (!enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD)
 541             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE)
 542             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_START)
 543             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_END)
 544             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_START)
 545             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT)
 546             || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH)
 547             ) {
 548         NSK_COMPLAIN0("Events could not be enabled");
 549         nsk_jvmti_setFailStatus();
 550         return JNI_ERR;
 551     }
 552 
 553     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
 554         return JNI_ERR;
 555 
 556     currentPhase = JVMTI_PHASE_PRIMORDIAL;
 557 
 558     return JNI_OK;
 559 }
 560 
 561 }