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 <stdlib.h> 25 #include <string.h> 26 #include "jni_tools.h" 27 #include "agent_common.h" 28 #include "jvmti_tools.h" 29 30 extern "C" { 31 32 #define MAX_DEPTH 1024 33 34 /* ========================================================================== */ 35 36 static const int NUMBER_OF_SAMPLES = 1000; 37 static const int DISPLAYING_FREQUENCY = 100; 38 static const jlong SAMPLING_INTERVAL = 10; 39 40 /* scaffold objects */ 41 static jlong timeout = 0; 42 43 /* test objects */ 44 static jthread thread = NULL; 45 static jrawMonitorID waitLock = NULL; 46 static jrawMonitorID frameLock = NULL; 47 static int sampleCount = 0; 48 static volatile int depth = 0; 49 static jvmtiFrameInfo sampleStack[MAX_DEPTH]; 50 static jint frameCount = 0; 51 static jvmtiFrameInfo frameBuffer[MAX_DEPTH]; 52 53 /* ========================================================================== */ 54 55 static int prepare(jvmtiEnv* jvmti, JNIEnv* jni) { 56 const char* THREAD_NAME = "Debuggee Thread"; 57 jvmtiThreadInfo info; 58 jthread *threads = NULL; 59 jint threads_count = 0; 60 int i; 61 62 NSK_DISPLAY0("Prepare: find tested thread\n"); 63 64 /* get all live threads */ 65 if (!NSK_JVMTI_VERIFY(jvmti->GetAllThreads(&threads_count, &threads))) 66 return NSK_FALSE; 67 68 if (!NSK_VERIFY(threads_count > 0 && threads != NULL)) 69 return NSK_FALSE; 70 71 /* find tested thread */ 72 for (i = 0; i < threads_count; i++) { 73 if (!NSK_VERIFY(threads[i] != NULL)) 74 return NSK_FALSE; 75 76 /* get thread information */ 77 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(threads[i], &info))) 78 return NSK_FALSE; 79 80 NSK_DISPLAY3(" thread #%d (%s): %p\n", i, info.name, threads[i]); 81 82 /* find by name */ 83 if (info.name != NULL && (strcmp(info.name, THREAD_NAME) == 0)) { 84 thread = threads[i]; 85 } 86 87 if (info.name != NULL) { 88 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)info.name))) 89 return NSK_FALSE; 90 } 91 } 92 93 /* deallocate threads list */ 94 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)threads))) 95 return NSK_FALSE; 96 97 if (thread == NULL) { 98 NSK_COMPLAIN0("Debuggee thread not found"); 99 return NSK_FALSE; 100 } 101 102 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("waitLock", &waitLock))) 103 return NSK_FALSE; 104 105 return NSK_TRUE; 106 } 107 108 /* ============================================================================= */ 109 110 static int wait_for(jvmtiEnv* jvmti, jlong millis) { 111 112 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(waitLock))) 113 return NSK_FALSE; 114 115 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorWait(waitLock, millis))) 116 nsk_jvmti_setFailStatus(); 117 118 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(waitLock))) 119 return NSK_FALSE; 120 121 return NSK_TRUE; 122 } 123 124 static int displayFrameInfo(jvmtiEnv* jvmti, jint i) { 125 char buffer[32]; 126 char *name = NULL; 127 char *signature = NULL; 128 129 if (!NSK_JVMTI_VERIFY(jvmti->GetMethodName(frameBuffer[frameCount-1-i].method, &name, &signature, NULL))) 130 return NSK_FALSE; 131 132 NSK_DISPLAY4(" got[%d] method: %s%s, location: %s\n", i, name, 133 signature, jlong_to_string(frameBuffer[frameCount-1-i].location, buffer)); 134 if (name != NULL) 135 jvmti->Deallocate((unsigned char*)name); 136 if (signature != NULL) 137 jvmti->Deallocate((unsigned char*)signature); 138 139 if (!NSK_JVMTI_VERIFY(jvmti->GetMethodName(sampleStack[i].method, &name, &signature, NULL))) 140 return NSK_FALSE; 141 142 NSK_DISPLAY4(" exp[%d] method: %s%s, location: %s\n", i, name, 143 signature, jlong_to_string(sampleStack[i].location, buffer)); 144 if (name != NULL) 145 jvmti->Deallocate((unsigned char*)name); 146 if (signature != NULL) 147 jvmti->Deallocate((unsigned char*)signature); 148 149 return NSK_TRUE; 150 } 151 152 static int complainFrameInfo(jvmtiEnv* jvmti, jint i) { 153 char buffer[32]; 154 char *name = NULL; 155 char *signature = NULL; 156 157 if (!NSK_JVMTI_VERIFY(jvmti->GetMethodName(frameBuffer[frameCount-1-i].method, &name, &signature, NULL))) 158 return NSK_FALSE; 159 160 NSK_COMPLAIN3(" got: method=%s%s, location=%s\n", name, signature, 161 jlong_to_string(frameBuffer[frameCount-1-i].location, buffer)); 162 if (name != NULL) 163 jvmti->Deallocate((unsigned char*)name); 164 if (signature != NULL) 165 jvmti->Deallocate((unsigned char*)signature); 166 167 if (!NSK_JVMTI_VERIFY(jvmti->GetMethodName(sampleStack[i].method, &name, &signature, NULL))) 168 return NSK_FALSE; 169 170 NSK_COMPLAIN3(" expected: method=%s%s, location=%s\n", name, signature, 171 jlong_to_string(sampleStack[i].location, buffer)); 172 if (name != NULL) 173 jvmti->Deallocate((unsigned char*)name); 174 if (signature != NULL) 175 jvmti->Deallocate((unsigned char*)signature); 176 177 return NSK_TRUE; 178 } 179 180 static int checkStackTrace(jvmtiEnv* jvmti, JNIEnv* jni) { 181 jint i; 182 int res = NSK_TRUE; 183 int displayFlag = 184 (nsk_getVerboseMode() && (sampleCount % DISPLAYING_FREQUENCY) == 0); 185 186 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(frameLock))) 187 return NSK_FALSE; 188 189 /* get stack trace */ 190 if (!NSK_JVMTI_VERIFY(jvmti->GetStackTrace(thread, 0, MAX_DEPTH, frameBuffer, &frameCount))) { 191 res = NSK_FALSE; 192 } else { 193 if (displayFlag) { 194 NSK_DISPLAY3("Sample #%d, frameCount: %d, depth: %d\n", 195 sampleCount, frameCount, depth); 196 } 197 if (!NSK_VERIFY(frameCount >= depth)) { 198 NSK_COMPLAIN3("Sample #%d, wrong frameCount: %d, expected >= %d\n", 199 sampleCount, frameCount, depth); 200 res = NSK_FALSE; 201 } else { 202 for (i = 0; i < depth; i++) { 203 if (displayFlag && !displayFrameInfo(jvmti, i)) 204 res = NSK_FALSE; 205 if (!NSK_VERIFY(sampleStack[i].method == 206 frameBuffer[frameCount-1-i].method) || 207 !NSK_VERIFY(sampleStack[i].location == 208 frameBuffer[frameCount-1-i].location)) { 209 210 NSK_COMPLAIN3("Sample #%d, depth=%d, wrong frame [%d]:\n", 211 sampleCount, depth, i); 212 complainFrameInfo(jvmti, i); 213 res = NSK_FALSE; 214 } 215 } 216 } 217 } 218 219 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(frameLock))) 220 return NSK_FALSE; 221 222 return res; 223 } 224 225 /* ========================================================================== */ 226 227 /* agent algorithm */ 228 static void JNICALL 229 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 230 231 /* wait for initial sync */ 232 if (!nsk_jvmti_waitForSync(timeout)) 233 return; 234 235 if (!prepare(jvmti, jni)) { 236 nsk_jvmti_setFailStatus(); 237 return; 238 } 239 240 /* sample stack of the tested thread */ 241 for (sampleCount = 0; 242 sampleCount < NUMBER_OF_SAMPLES && !nsk_jvmti_isFailStatus(); 243 sampleCount++) { 244 wait_for(jvmti, SAMPLING_INTERVAL); 245 if (!checkStackTrace(jvmti, jni)) 246 nsk_jvmti_setFailStatus(); 247 } 248 249 /* resume debugee after last sync */ 250 if (!nsk_jvmti_resumeSync()) 251 return; 252 } 253 254 /* ========================================================================== */ 255 256 JNIEXPORT jint JNICALL 257 Java_nsk_jvmti_scenarios_sampling_SP07_sp07t001Thread_wrapper(JNIEnv* jni, 258 jobject obj, jint i) { 259 jint result = 0; 260 jclass klass = NULL; 261 jmethodID method = NULL; 262 jvmtiEnv* jvmti = nsk_jvmti_getAgentJVMTIEnv(); 263 264 if (!NSK_VERIFY(depth < MAX_DEPTH)) { 265 nsk_jvmti_setFailStatus(); 266 return 0; 267 } 268 269 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(frameLock))) 270 return NSK_FALSE; 271 272 if (!NSK_JVMTI_VERIFY(jvmti->GetFrameLocation(NULL, 1, &sampleStack[depth].method, &sampleStack[depth].location))) { 273 nsk_jvmti_setFailStatus(); 274 return 0; 275 } 276 277 depth++; 278 279 if (!NSK_JVMTI_VERIFY(jvmti->GetFrameLocation(NULL, 0, &sampleStack[depth].method, &sampleStack[depth].location))) { 280 nsk_jvmti_setFailStatus(); 281 return 0; 282 } 283 284 depth++; 285 286 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(frameLock))) 287 return NSK_FALSE; 288 289 if (!NSK_JNI_VERIFY(jni, (klass = jni->GetObjectClass(obj)) != NULL)) { 290 nsk_jvmti_setFailStatus(); 291 return 0; 292 } 293 294 if (!NSK_JNI_VERIFY(jni, (method = jni->GetMethodID(klass, "fibonacci", "(I)I")) != NULL)) { 295 nsk_jvmti_setFailStatus(); 296 return 0; 297 } 298 299 result = jni->CallIntMethod(obj, method, i); 300 301 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(frameLock))) 302 return NSK_FALSE; 303 304 depth--; 305 depth--; 306 307 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(frameLock))) 308 return NSK_FALSE; 309 310 return result; 311 } 312 313 /* ========================================================================== */ 314 315 /* agent library initialization */ 316 #ifdef STATIC_BUILD 317 JNIEXPORT jint JNICALL Agent_OnLoad_sp07t001(JavaVM *jvm, char *options, void *reserved) { 318 return Agent_Initialize(jvm, options, reserved); 319 } 320 JNIEXPORT jint JNICALL Agent_OnAttach_sp07t001(JavaVM *jvm, char *options, void *reserved) { 321 return Agent_Initialize(jvm, options, reserved); 322 } 323 JNIEXPORT jint JNI_OnLoad_sp07t001(JavaVM *jvm, char *options, void *reserved) { 324 return JNI_VERSION_1_8; 325 } 326 #endif 327 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 328 jvmtiEnv* jvmti = NULL; 329 330 /* init framework and parse options */ 331 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 332 return JNI_ERR; 333 334 timeout = nsk_jvmti_getWaitTime() * 60000; 335 NSK_DISPLAY1("Timeout: %d msc\n", (int)timeout); 336 337 /* create JVMTI environment */ 338 if (!NSK_VERIFY((jvmti = 339 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 340 return JNI_ERR; 341 342 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("frameLock", &frameLock))) 343 return NSK_FALSE; 344 345 /* register agent proc and arg */ 346 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 347 return JNI_ERR; 348 349 return JNI_OK; 350 } 351 352 /* ========================================================================== */ 353 354 }