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 <stdio.h> 25 #include <string.h> 26 #include <jvmti.h> 27 #include "agent_common.h" 28 29 #include "nsk_tools.h" 30 #include "jni_tools.h" 31 #include "JVMTITools.h" 32 #include "jvmti_tools.h" 33 34 extern "C" { 35 36 #define OBJ_MAX_COUNT 100000 37 38 static JNIEnv *jni = NULL; 39 static jvmtiEnv *jvmti = NULL; 40 static jvmtiEventCallbacks callbacks; 41 static jvmtiCapabilities caps; 42 43 static jlong timeout = 0; 44 45 static const char* DEBUGEE_SIGNATURE = "Lnsk/jvmti/scenarios/allocation/AP04/ap04t001;"; 46 static const char* ROOT_SIGNATURE = "[Lnsk/jvmti/scenarios/allocation/AP04/ap04t001;"; 47 48 static const int eventsCount = 3; 49 static jvmtiEvent events[] = { 50 JVMTI_EVENT_OBJECT_FREE, 51 JVMTI_EVENT_GARBAGE_COLLECTION_START, 52 JVMTI_EVENT_GARBAGE_COLLECTION_FINISH 53 }; 54 55 static jclass debugeeClass = NULL; 56 static jfieldID rootFieldID = NULL; 57 static jmethodID unlockSecondaryID = NULL; 58 59 static volatile int eventCount = 0; 60 static volatile int iterationCount = 0; 61 static volatile int errorCount = 0; 62 63 /***********************************************************************/ 64 65 static jrawMonitorID counterMonitor_ptr = NULL; 66 67 static void increaseCounter(volatile int* counterPtr) { 68 69 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(counterMonitor_ptr))) { 70 nsk_jvmti_setFailStatus(); 71 } 72 73 (*counterPtr)++; 74 75 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(counterMonitor_ptr))) { 76 nsk_jvmti_setFailStatus(); 77 } 78 } 79 80 static void setCounter(volatile int* counterPtr, int value) { 81 82 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(counterMonitor_ptr))) { 83 nsk_jvmti_setFailStatus(); 84 } 85 86 *counterPtr = value; 87 88 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(counterMonitor_ptr))) { 89 nsk_jvmti_setFailStatus(); 90 } 91 } 92 93 static int getCounter(volatile int* counterPtr) { 94 int result; 95 96 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(counterMonitor_ptr))) { 97 nsk_jvmti_setFailStatus(); 98 } 99 100 result = *counterPtr; 101 102 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(counterMonitor_ptr))) { 103 nsk_jvmti_setFailStatus(); 104 } 105 106 return result; 107 } 108 109 /***********************************************************************/ 110 111 jvmtiIterationControl JNICALL 112 heapObjectCallback( jlong class_tag, 113 jlong size, 114 jlong* tag_ptr, 115 void* user_data) { 116 117 int count = 0; 118 119 /* clean eventCount on first iteration */ 120 if (getCounter(&iterationCount) == 0) { 121 setCounter(&eventCount, 0); 122 } 123 increaseCounter(&iterationCount); 124 125 /* check if eventCount is 0 for each iteration */ 126 count = getCounter(&eventCount); 127 if (count > 0) { 128 increaseCounter(&errorCount); 129 } 130 131 return JVMTI_ITERATION_CONTINUE; 132 } 133 134 /* jvmtiHeapRootCallback */ 135 jvmtiIterationControl JNICALL 136 heapRootCallback( jvmtiHeapRootKind root_kind, 137 jlong class_tag, 138 jlong size, 139 jlong* tag_ptr, 140 void* user_data) { 141 142 int count = 0; 143 144 /* clean eventCount on first iteration */ 145 if (getCounter(&iterationCount) == 0) { 146 setCounter(&eventCount, 0); 147 } 148 increaseCounter(&iterationCount); 149 150 /* check if eventCount is 0 for each iteration */ 151 count = getCounter(&eventCount); 152 if (count > 0) { 153 increaseCounter(&errorCount); 154 } 155 156 return JVMTI_ITERATION_CONTINUE; 157 } 158 159 /* jvmtiStackReferenceCallback */ 160 jvmtiIterationControl JNICALL 161 stackReferenceCallback( jvmtiHeapRootKind root_kind, 162 jlong class_tag, 163 jlong size, 164 jlong* tag_ptr, 165 jlong thread_tag, 166 jint depth, 167 jmethodID method, 168 jint slot, 169 void* user_data) { 170 171 int count = 0; 172 173 /* clean eventCount on first iteration */ 174 if (getCounter(&iterationCount) == 0) { 175 setCounter(&eventCount, 0); 176 } 177 increaseCounter(&iterationCount); 178 179 /* check if eventCount is 0 for each iteration */ 180 count = getCounter(&eventCount); 181 if (count > 0) { 182 increaseCounter(&errorCount); 183 } 184 185 return JVMTI_ITERATION_CONTINUE; 186 } 187 188 189 /* jvmtiObjectReferenceCallback */ 190 jvmtiIterationControl JNICALL 191 objectReferenceCallback( jvmtiObjectReferenceKind reference_kind, 192 jlong class_tag, 193 jlong size, 194 jlong* tag_ptr, 195 jlong referrer_tag, 196 jint referrer_index, 197 void* user_data) { 198 199 int count = 0; 200 201 /* clean eventCount on first iteration */ 202 if (getCounter(&iterationCount) == 0) { 203 setCounter(&eventCount, 0); 204 } 205 increaseCounter(&iterationCount); 206 207 /* check if eventCount is 0 for each iteration */ 208 count = getCounter(&eventCount); 209 if (count > 0) { 210 increaseCounter(&errorCount); 211 } 212 213 return JVMTI_ITERATION_CONTINUE; 214 } 215 216 217 /***********************************************************************/ 218 219 void JNICALL 220 ObjectFree(jvmtiEnv *jvmti_env, jlong tag) { 221 increaseCounter(&eventCount); 222 // NSK_DISPLAY0(" event: ObjectFree\n"); 223 } 224 225 void JNICALL 226 GarbageCollectionStart(jvmtiEnv *jvmti_env) { 227 increaseCounter(&eventCount); 228 NSK_DISPLAY0(" event: GarbageCollectionStart\n"); 229 } 230 231 void JNICALL 232 GarbageCollectionFinish(jvmtiEnv *jvmti_env) { 233 increaseCounter(&eventCount); 234 NSK_DISPLAY0(" event: GarbageCollectionFinish\n"); 235 } 236 237 /***********************************************************************/ 238 239 JNIEXPORT void JNICALL 240 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t001_setTag( JNIEnv* jni, 241 jclass klass, 242 jobject target, /* object to be tagged */ 243 jlong tag ) { 244 245 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(target, tag))) { 246 nsk_jvmti_setFailStatus(); 247 } 248 } 249 250 JNIEXPORT void JNICALL 251 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t001_forceGC( JNIEnv* jni, 252 jclass klass) { 253 254 NSK_DISPLAY0(" run: ForceGarbageCollection\n"); 255 if (!NSK_JVMTI_VERIFY(jvmti->ForceGarbageCollection())) { 256 nsk_jvmti_setFailStatus(); 257 } 258 } 259 260 JNIEXPORT void JNICALL 261 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t001_runIterateOverHeap( JNIEnv* jni, 262 jclass klass ) { 263 int count = 0; 264 265 setCounter(&errorCount, 0); 266 setCounter(&eventCount, 0); 267 setCounter(&iterationCount, 0); 268 269 NSK_DISPLAY0("Calling IterateOverHeap...\n"); 270 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_TAGGED, 271 heapObjectCallback, 272 NULL /*user_data*/))) { 273 nsk_jvmti_setFailStatus(); 274 } 275 NSK_DISPLAY0("IterateOverHeap finished.\n"); 276 277 NSK_DISPLAY1("Iterations count: %d\n", getCounter(&iterationCount)); 278 NSK_DISPLAY1("Events count: %d\n", getCounter(&eventCount)); 279 280 count = getCounter(&errorCount); 281 NSK_DISPLAY1("Errors detected: %d\n", count); 282 if (count > 0) { 283 NSK_COMPLAIN1("Events detected during heap iteration: %d\n", count); 284 nsk_jvmti_setFailStatus(); 285 } 286 } 287 288 JNIEXPORT void JNICALL 289 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t001_runIterateOverReachableObjects( JNIEnv* jni, 290 jclass klass ) { 291 int count = 0; 292 293 setCounter(&errorCount, 0); 294 setCounter(&eventCount, 0); 295 setCounter(&iterationCount, 0); 296 297 NSK_DISPLAY0("Calling IterateOverReachableObjects...\n"); 298 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverReachableObjects(heapRootCallback, 299 stackReferenceCallback, 300 objectReferenceCallback, 301 NULL /*user_data*/))) { 302 nsk_jvmti_setFailStatus(); 303 } 304 NSK_DISPLAY0("IterateOverReachableObjects finished.\n"); 305 306 NSK_DISPLAY1("Iterations count: %d\n", getCounter(&iterationCount)); 307 NSK_DISPLAY1("Events count: %d\n", getCounter(&eventCount)); 308 309 count = getCounter(&errorCount); 310 NSK_DISPLAY1("Errors detected: %d\n", count); 311 if (count > 0) { 312 NSK_COMPLAIN1("Events detected during heap iteration: %d\n", count); 313 nsk_jvmti_setFailStatus(); 314 } 315 } 316 317 JNIEXPORT void JNICALL 318 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t001_runIterateOverInstancesOfClass( JNIEnv* jni, 319 jclass klass ) { 320 int count = 0; 321 322 setCounter(&errorCount, 0); 323 setCounter(&eventCount, 0); 324 setCounter(&iterationCount, 0); 325 326 NSK_DISPLAY0("Calling IterateOverInstancesOfClass...\n"); 327 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverInstancesOfClass(debugeeClass, 328 JVMTI_HEAP_OBJECT_TAGGED, 329 heapObjectCallback, 330 NULL /*user_data*/))) { 331 nsk_jvmti_setFailStatus(); 332 } 333 NSK_DISPLAY0("IterateOverInstancesOfClass finished.\n"); 334 335 NSK_DISPLAY1("Iterations count: %d\n", getCounter(&iterationCount)); 336 NSK_DISPLAY1("Events count: %d\n", getCounter(&eventCount)); 337 338 count = getCounter(&errorCount); 339 NSK_DISPLAY1("Errors detected: %d\n", count); 340 if (count > 0) { 341 NSK_COMPLAIN1("Events detected during heap iteration: %d\n", count); 342 nsk_jvmti_setFailStatus(); 343 } 344 } 345 346 JNIEXPORT void JNICALL 347 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t001_runIterateOverObjectsReachableFromObject( JNIEnv* jni, 348 jclass klass ) { 349 350 jobject root = NULL; 351 int count = 0; 352 353 if (!NSK_JNI_VERIFY(jni, (root = 354 jni->GetStaticObjectField(debugeeClass, rootFieldID)) != NULL )) { 355 NSK_COMPLAIN0("GetStaticObjectField returned NULL for 'root' field value\n\n"); 356 nsk_jvmti_setFailStatus(); 357 return; 358 } 359 360 // release secondary lock 361 jni->CallStaticVoidMethod(debugeeClass, unlockSecondaryID); 362 363 setCounter(&errorCount, 0); 364 setCounter(&eventCount, 0); 365 setCounter(&iterationCount, 0); 366 367 NSK_DISPLAY0("Calling IterateOverObjectsReachableFromObject...\n"); 368 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverObjectsReachableFromObject(root, 369 objectReferenceCallback, 370 NULL /*user_data*/))) { 371 nsk_jvmti_setFailStatus(); 372 } 373 NSK_DISPLAY0("IterateOverObjectsReachableFromObject finished.\n"); 374 375 NSK_DISPLAY1("Iterations count: %d\n", getCounter(&iterationCount)); 376 NSK_DISPLAY1("Events count: %d\n", getCounter(&eventCount)); 377 378 count = getCounter(&errorCount); 379 NSK_DISPLAY1("Errors detected: %d\n", count); 380 if (count > 0) { 381 NSK_COMPLAIN1("Events detected during heap iteration: %d\n", count); 382 nsk_jvmti_setFailStatus(); 383 } 384 } 385 386 static void JNICALL 387 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 388 389 NSK_DISPLAY0("Wait for debugee start\n\n"); 390 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 391 return; 392 393 NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_SIGNATURE); 394 debugeeClass = nsk_jvmti_classBySignature(DEBUGEE_SIGNATURE); 395 if (debugeeClass == NULL) { 396 nsk_jvmti_setFailStatus(); 397 return; 398 } 399 400 if (!NSK_JNI_VERIFY(jni, (debugeeClass = (jclass)jni->NewGlobalRef(debugeeClass)) != NULL)) 401 return; 402 403 NSK_DISPLAY1("Find ID of 'root' field: %s\n", ROOT_SIGNATURE); 404 if (!NSK_JNI_VERIFY(jni, (rootFieldID = 405 jni->GetStaticFieldID(debugeeClass, "root", ROOT_SIGNATURE)) != NULL )) { 406 nsk_jvmti_setFailStatus(); 407 return; 408 } 409 410 NSK_DISPLAY1("Find ID of 'unlockSecondary' method: %s\n", ROOT_SIGNATURE); 411 if (!NSK_JNI_VERIFY(jni, (unlockSecondaryID = 412 jni->GetStaticMethodID(debugeeClass, "unlockSecondary", "()V")) != NULL )) { 413 nsk_jvmti_setFailStatus(); 414 return; 415 } 416 417 418 NSK_DISPLAY0("Let debugee to run test cases\n"); 419 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 420 return; 421 422 NSK_DISPLAY0("Wait for completion of test cases\n\n"); 423 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 424 return; 425 426 nsk_jvmti_enableEvents(JVMTI_DISABLE, eventsCount, events, NULL); 427 428 NSK_TRACE(jni->DeleteGlobalRef(debugeeClass)); 429 NSK_TRACE(jvmti->DestroyRawMonitor(counterMonitor_ptr)); 430 431 NSK_DISPLAY0("Let debugee to finish\n"); 432 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 433 return; 434 } 435 436 #ifdef STATIC_BUILD 437 JNIEXPORT jint JNICALL Agent_OnLoad_ap04t001(JavaVM *jvm, char *options, void *reserved) { 438 return Agent_Initialize(jvm, options, reserved); 439 } 440 JNIEXPORT jint JNICALL Agent_OnAttach_ap04t001(JavaVM *jvm, char *options, void *reserved) { 441 return Agent_Initialize(jvm, options, reserved); 442 } 443 JNIEXPORT jint JNI_OnLoad_ap04t001(JavaVM *jvm, char *options, void *reserved) { 444 return JNI_VERSION_1_8; 445 } 446 #endif 447 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 448 /* init framework and parse options */ 449 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 450 return JNI_ERR; 451 452 /* create JVMTI environment */ 453 if (!NSK_VERIFY((jvmti = 454 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 455 return JNI_ERR; 456 457 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("counterMonitor", &counterMonitor_ptr))) { 458 return JNI_ERR; 459 } 460 461 memset(&caps, 0, sizeof(jvmtiCapabilities)); 462 caps.can_tag_objects = 1; 463 caps.can_generate_object_free_events = 1; 464 caps.can_generate_garbage_collection_events = 1; 465 466 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) 467 return JNI_ERR; 468 469 if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps))) 470 return JNI_ERR; 471 472 if (!caps.can_tag_objects) 473 NSK_DISPLAY0("Warning: tagging objects is not available\n"); 474 if (!caps.can_generate_object_free_events) 475 NSK_DISPLAY0("Warning: generation of object free events is not available\n"); 476 if (!caps.can_generate_garbage_collection_events) 477 NSK_DISPLAY0("Warning: generation of garbage collection events is not available\n"); 478 479 /* set event callback */ 480 NSK_DISPLAY0("setting event callbacks ...\n"); 481 (void) memset(&callbacks, 0, sizeof(callbacks)); 482 483 callbacks.ObjectFree = &ObjectFree; 484 callbacks.GarbageCollectionStart = &GarbageCollectionStart; 485 callbacks.GarbageCollectionFinish = &GarbageCollectionFinish; 486 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)))) 487 return JNI_ERR; 488 489 NSK_DISPLAY0("setting event callbacks done.\n"); 490 491 NSK_DISPLAY0("enabling JVMTI events ...\n"); 492 if (!nsk_jvmti_enableEvents(JVMTI_ENABLE, eventsCount, events, NULL)) { 493 return JNI_ERR; 494 } 495 NSK_DISPLAY0("enabling the events done.\n"); 496 497 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 498 return JNI_ERR; 499 NSK_DISPLAY0("agentProc has been set\n\n"); 500 501 return JNI_OK; 502 } 503 504 }