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(jvmti->SetEventNotificationMode(enable, eventsList[i], NULL))) { 147 nsk_jvmti_setFailStatus(); 148 return NSK_FALSE; 149 } 150 } 151 return NSK_TRUE; 152 } 153 154 /** 155 * Prepare data: 156 * - get threads array from static field 157 * - get each thread from array 158 * - make global refs 159 * - enable events 160 */ 161 static int prepare() { 162 jclass debugeeClass = NULL; 163 jfieldID threadsFieldID = NULL; 164 jobjectArray threadsArray = NULL; 165 jsize threadsArrayLength = 0; 166 jsize i; 167 168 /* find debugee class */ 169 if (!NSK_JNI_VERIFY(jni, (debugeeClass = jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) 170 return NSK_FALSE; 171 172 /* find static field with threads array */ 173 if (!NSK_JNI_VERIFY(jni, (threadsFieldID = 174 jni->GetStaticFieldID(debugeeClass, THREADS_FIELD_NAME, THREADS_FIELD_SIG)) != NULL)) 175 return NSK_FALSE; 176 177 /* get threads array from static field */ 178 if (!NSK_JNI_VERIFY(jni, (threadsArray = (jobjectArray) 179 jni->GetStaticObjectField(debugeeClass, threadsFieldID)) != NULL)) 180 return NSK_FALSE; 181 182 /* check array length */ 183 if (!NSK_JNI_VERIFY(jni, (threadsArrayLength = 184 jni->GetArrayLength(threadsArray)) == THREADS_COUNT)) 185 return NSK_FALSE; 186 187 /* get each thread from array */ 188 for (i = 0; i < THREADS_COUNT; i++) { 189 if (!NSK_JNI_VERIFY(jni, (threadsList[i] = (jthread) 190 jni->GetObjectArrayElement(threadsArray, i)) != NULL)) 191 return NSK_FALSE; 192 } 193 194 /* make global references to threads */ 195 for (i = 0; i < THREADS_COUNT; i++) { 196 if (!NSK_JNI_VERIFY(jni, (threadsList[i] = (jthread) 197 jni->NewGlobalRef(threadsList[i])) != NULL)) 198 return NSK_FALSE; 199 } 200 201 return enableEvents(JVMTI_ENABLE); 202 } 203 204 /** 205 * Testcase: check thread's stack on event 206 * 207 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 208 */ 209 static int checkThread(jthread thread, int i, const char* kind) { 210 jint framesCount = 0; 211 jint stackDepth = 0; 212 jvmtiFrameInfo stackFrames[MAX_STACK_DEPTH]; 213 214 NSK_DISPLAY3(" thread #%d (%s): %p\n", i, threadsName[i], (void*)thread); 215 216 /* get frames count */ 217 if (!NSK_JVMTI_VERIFY(jvmti->GetFrameCount(thread, &framesCount))) { 218 nsk_jvmti_setFailStatus(); 219 return NSK_TRUE; 220 } 221 NSK_DISPLAY1(" frames count: %d\n", (int)framesCount); 222 223 /* get stack frames */ 224 if (!NSK_JVMTI_VERIFY( 225 jvmti->GetStackTrace(thread, 0, MAX_STACK_DEPTH, stackFrames, &stackDepth))) { 226 nsk_jvmti_setFailStatus(); 227 return NSK_TRUE; 228 } 229 NSK_DISPLAY1(" stack depth: %d\n", (int)stackDepth); 230 231 /* check against emptyness */ 232 if (framesCount != 0) { 233 NSK_COMPLAIN5("Unexpected GetFramesCount() for %s thread #%d (%s):\n" 234 "# got frames: %d\n" 235 "# expected: %d\n", 236 kind, i, threadsName[i], 237 framesCount, 0); 238 nsk_jvmti_setFailStatus(); 239 } 240 if (stackDepth != 0) { 241 NSK_COMPLAIN5("Unexpected GetStackTrace() for %s thread #%d (%s):\n" 242 "# got frames: %d\n" 243 "# expected: %d\n", 244 kind, i, threadsName[i], 245 stackDepth, 0); 246 nsk_jvmti_setFailStatus(); 247 } 248 249 /* test may continue */ 250 return NSK_TRUE; 251 } 252 253 /** 254 * Clean data: 255 * - disable events 256 * - dispose global references to tested threads 257 */ 258 static int clean() { 259 int i; 260 261 /* disable events */ 262 enableEvents(JVMTI_DISABLE); 263 264 /* dispose global references to threads */ 265 for (i = 0; i < THREADS_COUNT; i++) { 266 NSK_TRACE(jni->DeleteGlobalRef(threadsList[i])); 267 } 268 269 return NSK_TRUE; 270 } 271 272 /* ============================================================================= */ 273 274 /** 275 * THREAD_START callback: 276 * - check thread's stack on THREAD_START 277 */ 278 JNIEXPORT void JNICALL 279 callbackThreadStart(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) { 280 int i; 281 282 /* check if thread is not NULL */ 283 if (!NSK_VERIFY(thread != NULL)) { 284 nsk_jvmti_setFailStatus(); 285 return; 286 } 287 288 /* check if event is for tested thread */ 289 for (i = 0; i < THREADS_COUNT; i++) { 290 if (jni->IsSameObject(threadsList[i], thread)) { 291 NSK_DISPLAY0("SUCCESS: expected THREAD_START event\n"); 292 eventsStart++; 293 294 /* check thread on event */ 295 checkThread(thread, i, "starting"); 296 break; 297 } 298 } 299 } 300 301 /** 302 * THREAD_END callback: 303 * - check thread's stack on THREAD_END 304 */ 305 JNIEXPORT void JNICALL 306 callbackThreadEnd(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) { 307 int i; 308 309 /* check if thread is not NULL */ 310 if (!NSK_VERIFY(thread != NULL)) { 311 nsk_jvmti_setFailStatus(); 312 return; 313 } 314 315 /* check if event is for tested thread */ 316 for (i = 0; i < THREADS_COUNT; i++) { 317 if (jni->IsSameObject(threadsList[i], thread)) { 318 NSK_DISPLAY0("SUCCESS: expected THREAD_START event\n"); 319 eventsEnd++; 320 321 /* check thread on event */ 322 checkThread(thread, i, "finishing"); 323 break; 324 } 325 } 326 } 327 328 /* ============================================================================= */ 329 330 static volatile int testedThreadRunning = NSK_FALSE; 331 static volatile int testedThreadShouldFinish = NSK_FALSE; 332 333 /** Native running method in tested thread. */ 334 JNIEXPORT void JNICALL 335 Java_nsk_jvmti_scenarios_sampling_SP05_sp05t002ThreadRunningNative_run(JNIEnv* jni, 336 jobject obj) { 337 volatile int i = 0, n = 1000; 338 339 /* run in a loop */ 340 testedThreadRunning = NSK_TRUE; 341 while (!testedThreadShouldFinish) { 342 if (n <= 0) 343 n = 1000; 344 if (i >= n) 345 i = 0; 346 i++; 347 } 348 testedThreadRunning = NSK_FALSE; 349 } 350 351 /** Wait for native method is running. */ 352 JNIEXPORT jboolean JNICALL 353 Java_nsk_jvmti_scenarios_sampling_SP05_sp05t002ThreadRunningNative_checkStarted(JNIEnv* jni, 354 jobject obj) { 355 while (!testedThreadRunning) { 356 nsk_jvmti_sleep(1000); 357 } 358 return testedThreadRunning ? JNI_TRUE : JNI_FALSE; 359 } 360 361 /** Let native method to finish. */ 362 JNIEXPORT void JNICALL 363 Java_nsk_jvmti_scenarios_sampling_SP05_sp05t002ThreadRunningNative_letFinish(JNIEnv* jni, 364 jobject obj) { 365 testedThreadShouldFinish = NSK_TRUE; 366 } 367 368 /* ============================================================================= */ 369 370 /** Aent library initialization. */ 371 #ifdef STATIC_BUILD 372 JNIEXPORT jint JNICALL Agent_OnLoad_sp05t002(JavaVM *jvm, char *options, void *reserved) { 373 return Agent_Initialize(jvm, options, reserved); 374 } 375 JNIEXPORT jint JNICALL Agent_OnAttach_sp05t002(JavaVM *jvm, char *options, void *reserved) { 376 return Agent_Initialize(jvm, options, reserved); 377 } 378 JNIEXPORT jint JNI_OnLoad_sp05t002(JavaVM *jvm, char *options, void *reserved) { 379 return JNI_VERSION_1_8; 380 } 381 #endif 382 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 383 /* init framework and parse options */ 384 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 385 return JNI_ERR; 386 387 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 388 389 /* create JVMTI environment */ 390 if (!NSK_VERIFY((jvmti = 391 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 392 return JNI_ERR; 393 394 /* set events callbacks */ 395 { 396 jvmtiEventCallbacks eventCallbacks; 397 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 398 eventCallbacks.ThreadStart = callbackThreadStart; 399 eventCallbacks.ThreadEnd = callbackThreadEnd; 400 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)))) 401 return JNI_ERR; 402 } 403 404 /* register agent proc and arg */ 405 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 406 return JNI_ERR; 407 408 return JNI_OK; 409 } 410 411 /* ============================================================================= */ 412 413 }