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