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 <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 /* constant names */ 35 #define DEBUGEE_CLASS_NAME "nsk/jvmti/scenarios/sampling/SP05/sp05t002" 36 #define THREAD_CLASS_NAME "nsk/jvmti/scenarios/sampling/SP05/sp05t002Thread" 37 #define THREADS_FIELD_NAME "threads" 38 #define THREADS_FIELD_SIG "[L" THREAD_CLASS_NAME ";" 39 40 /* scaffold objects */ 41 static JNIEnv* jni = NULL; 42 static jvmtiEnv *jvmti = NULL; 43 static jlong timeout = 0; 44 45 /* number of tested threads and events */ 46 #define THREADS_COUNT 2 47 #define EVENTS_COUNT 2 48 #define MAX_STACK_DEPTH 64 49 50 /* tested events */ 51 static jvmtiEvent eventsList[EVENTS_COUNT] = { 52 JVMTI_EVENT_THREAD_START, 53 JVMTI_EVENT_THREAD_END 54 }; 55 56 /* tested threads names */ 57 static const char* threadsName[THREADS_COUNT] = { 58 "threadRunningJava", 59 "threadRunningNative" 60 }; 61 62 /* references to tested threads */ 63 static jthread threadsList[THREADS_COUNT]; 64 65 /* events conunts */ 66 static volatile int eventsStart = 0; 67 static volatile int eventsEnd = 0; 68 69 /* ============================================================================= */ 70 71 /* testcase(s) */ 72 static int prepare(); 73 static int checkThread(jthread thread, int i, const char* kind); 74 static int clean(); 75 76 /* ============================================================================= */ 77 78 /** Agent algorithm. */ 79 static void JNICALL 80 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { 81 jni = agentJNI; 82 83 /* wait for initial sync */ 84 if (!nsk_jvmti_waitForSync(timeout)) 85 return; 86 87 /* testcase(s) */ 88 { 89 /* obtain threads list */ 90 if (!prepare()) { 91 nsk_jvmti_setFailStatus(); 92 return; 93 } 94 95 /* clean events count */ 96 eventsStart = 0; 97 eventsEnd = 0; 98 99 /* testcase #1: check threads on THREAD_START */ 100 NSK_DISPLAY0("Testcase #1: check threads on THREAD_START\n"); 101 if (!(NSK_VERIFY(nsk_jvmti_resumeSync()) 102 && NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))) 103 return; 104 105 /* testcase #2: check threads on THREAD_END */ 106 NSK_DISPLAY0("Testcase #2: check threads on THREAD_END\n"); 107 if (!(NSK_VERIFY(nsk_jvmti_resumeSync()) 108 && NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))) 109 return; 110 111 /* check events count */ 112 if (eventsStart != THREADS_COUNT) { 113 NSK_COMPLAIN2("Unexpected number of THREAD_START events:\n" 114 "# received: %d\n" 115 "# expected: %d\n", 116 eventsStart, THREADS_COUNT); 117 } 118 if (eventsEnd != THREADS_COUNT) { 119 NSK_COMPLAIN2("Unexpected number of THREAD_END events:\n" 120 "# received: %d\n" 121 "# expected: %d\n", 122 eventsEnd, THREADS_COUNT); 123 } 124 125 /* clean threads references */ 126 if (!clean()) { 127 nsk_jvmti_setFailStatus(); 128 return; 129 } 130 } 131 132 /* resume debugee after last sync */ 133 if (!nsk_jvmti_resumeSync()) 134 return; 135 } 136 137 /* ============================================================================= */ 138 139 /** 140 * Enable or disable tested events. 141 */ 142 static int enableEvents(jvmtiEventMode enable) { 143 int i; 144 145 for (i = 0; i < EVENTS_COUNT; i++) { 146 if (!NSK_JVMTI_VERIFY( 147 NSK_CPP_STUB4(SetEventNotificationMode, jvmti, enable, 148 eventsList[i], NULL))) { 149 nsk_jvmti_setFailStatus(); 150 return NSK_FALSE; 151 } 152 } 153 return NSK_TRUE; 154 } 155 156 /** 157 * Prepare data: 158 * - get threads array from static field 159 * - get each thread from array 160 * - make global refs 161 * - enable events 162 */ 163 static int prepare() { 164 jclass debugeeClass = NULL; 165 jfieldID threadsFieldID = NULL; 166 jobjectArray threadsArray = NULL; 167 jsize threadsArrayLength = 0; 168 jsize i; 169 170 /* find debugee class */ 171 if (!NSK_JNI_VERIFY(jni, (debugeeClass = 172 NSK_CPP_STUB2(FindClass, jni, DEBUGEE_CLASS_NAME)) != NULL)) 173 return NSK_FALSE; 174 175 /* find static field with threads array */ 176 if (!NSK_JNI_VERIFY(jni, (threadsFieldID = 177 NSK_CPP_STUB4(GetStaticFieldID, jni, debugeeClass, 178 THREADS_FIELD_NAME, THREADS_FIELD_SIG)) != NULL)) 179 return NSK_FALSE; 180 181 /* get threads array from static field */ 182 if (!NSK_JNI_VERIFY(jni, (threadsArray = (jobjectArray) 183 NSK_CPP_STUB3(GetStaticObjectField, jni, debugeeClass, threadsFieldID)) != NULL)) 184 return NSK_FALSE; 185 186 /* check array length */ 187 if (!NSK_JNI_VERIFY(jni, (threadsArrayLength = 188 NSK_CPP_STUB2(GetArrayLength, jni, threadsArray)) == THREADS_COUNT)) 189 return NSK_FALSE; 190 191 /* get each thread from array */ 192 for (i = 0; i < THREADS_COUNT; i++) { 193 if (!NSK_JNI_VERIFY(jni, (threadsList[i] = (jthread) 194 NSK_CPP_STUB3(GetObjectArrayElement, jni, threadsArray, i)) != NULL)) 195 return NSK_FALSE; 196 } 197 198 /* make global references to threads */ 199 for (i = 0; i < THREADS_COUNT; i++) { 200 if (!NSK_JNI_VERIFY(jni, (threadsList[i] = (jthread) 201 NSK_CPP_STUB2(NewGlobalRef, jni, threadsList[i])) != NULL)) 202 return NSK_FALSE; 203 } 204 205 return enableEvents(JVMTI_ENABLE); 206 } 207 208 /** 209 * Testcase: check thread's stack on event 210 * 211 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 212 */ 213 static int checkThread(jthread thread, int i, const char* kind) { 214 jint framesCount = 0; 215 jint stackDepth = 0; 216 jvmtiFrameInfo stackFrames[MAX_STACK_DEPTH]; 217 218 NSK_DISPLAY3(" thread #%d (%s): %p\n", i, threadsName[i], (void*)thread); 219 220 /* get frames count */ 221 if (!NSK_JVMTI_VERIFY( 222 NSK_CPP_STUB3(GetFrameCount, jvmti, thread, &framesCount))) { 223 nsk_jvmti_setFailStatus(); 224 return NSK_TRUE; 225 } 226 NSK_DISPLAY1(" frames count: %d\n", (int)framesCount); 227 228 /* get stack frames */ 229 if (!NSK_JVMTI_VERIFY( 230 NSK_CPP_STUB6(GetStackTrace, jvmti, thread, 0, MAX_STACK_DEPTH, 231 stackFrames, &stackDepth))) { 232 nsk_jvmti_setFailStatus(); 233 return NSK_TRUE; 234 } 235 NSK_DISPLAY1(" stack depth: %d\n", (int)stackDepth); 236 237 /* check against emptyness */ 238 if (framesCount != 0) { 239 NSK_COMPLAIN5("Unexpected GetFramesCount() for %s thread #%d (%s):\n" 240 "# got frames: %d\n" 241 "# expected: %d\n", 242 kind, i, threadsName[i], 243 framesCount, 0); 244 nsk_jvmti_setFailStatus(); 245 } 246 if (stackDepth != 0) { 247 NSK_COMPLAIN5("Unexpected GetStackTrace() for %s thread #%d (%s):\n" 248 "# got frames: %d\n" 249 "# expected: %d\n", 250 kind, i, threadsName[i], 251 stackDepth, 0); 252 nsk_jvmti_setFailStatus(); 253 } 254 255 /* test may continue */ 256 return NSK_TRUE; 257 } 258 259 /** 260 * Clean data: 261 * - disable events 262 * - dispose global references to tested threads 263 */ 264 static int clean() { 265 int i; 266 267 /* disable events */ 268 enableEvents(JVMTI_DISABLE); 269 270 /* dispose global references to threads */ 271 for (i = 0; i < THREADS_COUNT; i++) { 272 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, threadsList[i])); 273 } 274 275 return NSK_TRUE; 276 } 277 278 /* ============================================================================= */ 279 280 /** 281 * THREAD_START callback: 282 * - check thread's stack on THREAD_START 283 */ 284 JNIEXPORT void JNICALL 285 callbackThreadStart(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) { 286 int i; 287 288 /* check if thread is not NULL */ 289 if (!NSK_VERIFY(thread != NULL)) { 290 nsk_jvmti_setFailStatus(); 291 return; 292 } 293 294 /* check if event is for tested thread */ 295 for (i = 0; i < THREADS_COUNT; i++) { 296 if (NSK_CPP_STUB3(IsSameObject, jni, threadsList[i], thread)) { 297 NSK_DISPLAY0("SUCCESS: expected THREAD_START event\n"); 298 eventsStart++; 299 300 /* check thread on event */ 301 checkThread(thread, i, "starting"); 302 break; 303 } 304 } 305 } 306 307 /** 308 * THREAD_END callback: 309 * - check thread's stack on THREAD_END 310 */ 311 JNIEXPORT void JNICALL 312 callbackThreadEnd(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) { 313 int i; 314 315 /* check if thread is not NULL */ 316 if (!NSK_VERIFY(thread != NULL)) { 317 nsk_jvmti_setFailStatus(); 318 return; 319 } 320 321 /* check if event is for tested thread */ 322 for (i = 0; i < THREADS_COUNT; i++) { 323 if (NSK_CPP_STUB3(IsSameObject, jni, threadsList[i], thread)) { 324 NSK_DISPLAY0("SUCCESS: expected THREAD_START event\n"); 325 eventsEnd++; 326 327 /* check thread on event */ 328 checkThread(thread, i, "finishing"); 329 break; 330 } 331 } 332 } 333 334 /* ============================================================================= */ 335 336 static volatile int testedThreadRunning = NSK_FALSE; 337 static volatile int testedThreadShouldFinish = NSK_FALSE; 338 339 /** Native running method in tested thread. */ 340 JNIEXPORT void JNICALL 341 Java_nsk_jvmti_scenarios_sampling_SP05_sp05t002ThreadRunningNative_run(JNIEnv* jni, 342 jobject obj) { 343 volatile int i = 0, n = 1000; 344 345 /* run in a loop */ 346 testedThreadRunning = NSK_TRUE; 347 while (!testedThreadShouldFinish) { 348 if (n <= 0) 349 n = 1000; 350 if (i >= n) 351 i = 0; 352 i++; 353 } 354 testedThreadRunning = NSK_FALSE; 355 } 356 357 /** Wait for native method is running. */ 358 JNIEXPORT jboolean JNICALL 359 Java_nsk_jvmti_scenarios_sampling_SP05_sp05t002ThreadRunningNative_checkStarted(JNIEnv* jni, 360 jobject obj) { 361 while (!testedThreadRunning) { 362 nsk_jvmti_sleep(1000); 363 } 364 return testedThreadRunning ? JNI_TRUE : JNI_FALSE; 365 } 366 367 /** Let native method to finish. */ 368 JNIEXPORT void JNICALL 369 Java_nsk_jvmti_scenarios_sampling_SP05_sp05t002ThreadRunningNative_letFinish(JNIEnv* jni, 370 jobject obj) { 371 testedThreadShouldFinish = NSK_TRUE; 372 } 373 374 /* ============================================================================= */ 375 376 /** Aent library initialization. */ 377 #ifdef STATIC_BUILD 378 JNIEXPORT jint JNICALL Agent_OnLoad_sp05t002(JavaVM *jvm, char *options, void *reserved) { 379 return Agent_Initialize(jvm, options, reserved); 380 } 381 JNIEXPORT jint JNICALL Agent_OnAttach_sp05t002(JavaVM *jvm, char *options, void *reserved) { 382 return Agent_Initialize(jvm, options, reserved); 383 } 384 JNIEXPORT jint JNI_OnLoad_sp05t002(JavaVM *jvm, char *options, void *reserved) { 385 return JNI_VERSION_1_8; 386 } 387 #endif 388 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 389 /* init framework and parse options */ 390 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 391 return JNI_ERR; 392 393 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 394 395 /* create JVMTI environment */ 396 if (!NSK_VERIFY((jvmti = 397 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 398 return JNI_ERR; 399 400 /* set events callbacks */ 401 { 402 jvmtiEventCallbacks eventCallbacks; 403 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 404 eventCallbacks.ThreadStart = callbackThreadStart; 405 eventCallbacks.ThreadEnd = callbackThreadEnd; 406 if (!NSK_JVMTI_VERIFY( 407 NSK_CPP_STUB3(SetEventCallbacks, jvmti, 408 &eventCallbacks, sizeof(eventCallbacks)))) 409 return JNI_ERR; 410 } 411 412 /* register agent proc and arg */ 413 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 414 return JNI_ERR; 415 416 return JNI_OK; 417 } 418 419 /* ============================================================================= */ 420 421 }