1 /* 2 * Copyright (c) 2007, 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 "jni_tools.h" 28 #include "agent_common.h" 29 30 extern "C" { 31 32 #define STATUS_FAILED 2 33 #define PASSED 0 34 35 #define JVMTI_ERROR_CHECK(str,res) \ 36 if (res != JVMTI_ERROR_NONE) { \ 37 printf("%s %d\n" ,str, res); \ 38 return res; \ 39 } 40 41 #define JVMTI_ERROR_CHECK_EXPECTED_ERROR(str,res,err) \ 42 if (res != err) { \ 43 printf("%s unexpected error %d\n", str, res); \ 44 return res; \ 45 } 46 47 #define JVMTI_ERROR_CHECK_VOID(str,res) \ 48 if (res != JVMTI_ERROR_NONE) { \ 49 printf("%s %d\n" ,str, res); \ 50 iGlobalStatus = STATUS_FAILED; \ 51 } 52 53 #define JVMTI_ERROR_CHECK_EXPECTED_ERROR_VOID(str,res,err) \ 54 if (res != err) { \ 55 printf("%s unexpected error %d\n",str, res); \ 56 iGlobalStatus = STATUS_FAILED; \ 57 } 58 59 60 static jvmtiEnv *jvmti; 61 static jint iGlobalStatus = PASSED; 62 static jvmtiCapabilities jvmti_caps; 63 static jrawMonitorID jraw_monitor; 64 65 66 #define MAX_FRAMES_CNT 30 67 static jvmtiStackInfo *stack_buf1 = NULL; 68 static jvmtiStackInfo *stack_buf2 = NULL; 69 static jthread *thread_list = NULL; 70 static jvmtiThreadInfo *thread_info = NULL; 71 static jint threads_count = 0; 72 73 74 #ifdef STATIC_BUILD 75 JNIEXPORT jint JNICALL Agent_OnLoad_getallstktr001(JavaVM *jvm, char *options, void *reserved) { 76 return Agent_Initialize(jvm, options, reserved); 77 } 78 JNIEXPORT jint JNICALL Agent_OnAttach_getallstktr001(JavaVM *jvm, char *options, void *reserved) { 79 return Agent_Initialize(jvm, options, reserved); 80 } 81 JNIEXPORT jint JNI_OnLoad_getallstktr001(JavaVM *jvm, char *options, void *reserved) { 82 return JNI_VERSION_1_8; 83 } 84 #endif 85 jint Agent_Initialize(JavaVM * jvm, char *options, void *reserved) { 86 jint res; 87 88 res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1); 89 if (res < 0) { 90 printf("Wrong result of a valid call to GetEnv!\n"); 91 return JNI_ERR; 92 } 93 94 /* Add capabilities */ 95 res = jvmti->GetPotentialCapabilities(&jvmti_caps); 96 JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res); 97 98 res = jvmti->AddCapabilities(&jvmti_caps); 99 JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res); 100 101 return JNI_OK; 102 } 103 104 105 JNIEXPORT jint JNICALL 106 Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_GetResult( 107 JNIEnv * env, jclass cls) 108 { 109 return iGlobalStatus; 110 } 111 112 113 JNIEXPORT void JNICALL 114 Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_CreateRawMonitor( 115 JNIEnv * env, jclass cls) 116 { 117 jvmtiError ret; 118 char sz[128]; 119 120 sprintf(sz, "Raw-monitor"); 121 ret = jvmti->CreateRawMonitor(sz, &jraw_monitor); 122 123 if (ret != JVMTI_ERROR_NONE) { 124 printf("Error: Raw monitor create %d \n", ret); 125 iGlobalStatus = STATUS_FAILED; 126 } 127 } 128 129 JNIEXPORT void JNICALL 130 Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_RawMonitorEnter( 131 JNIEnv * env, jclass cls) 132 { 133 jvmtiError ret; 134 135 ret = jvmti->RawMonitorEnter(jraw_monitor); 136 137 if (ret != JVMTI_ERROR_NONE) { 138 printf("Error: Raw monitor enter %d \n", ret); 139 iGlobalStatus = STATUS_FAILED; 140 } 141 } 142 143 JNIEXPORT void JNICALL 144 Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_RawMonitorExit( 145 JNIEnv * env, jclass cls) 146 { 147 jvmtiError ret; 148 149 ret = jvmti->RawMonitorExit(jraw_monitor); 150 151 if (ret != JVMTI_ERROR_NONE) { 152 printf("Error: RawMonitorExit %d \n", ret); 153 iGlobalStatus = STATUS_FAILED; 154 } 155 } 156 157 void compare_all_frames(int ti, int frames_count, 158 jvmtiFrameInfo *fr_buf1, 159 jvmtiFrameInfo *fr_buf2) 160 { 161 int fi; 162 jvmtiFrameInfo *fr1, *fr2; 163 164 for (fi = 0; fi < frames_count; fi++) { 165 fr1 = &fr_buf1[fi]; 166 fr2 = &fr_buf2[fi]; 167 if (fr1->method != fr2->method) { 168 printf("FAILED: compare frame: thread %d: frame %d: " 169 "different methods", ti, fi); 170 iGlobalStatus = STATUS_FAILED; 171 return; 172 } 173 if (fr1->location != fr2->location) { 174 printf("FAILED: compare frame: thread %d: frame %d: " 175 "different locations", ti, fi); 176 iGlobalStatus = STATUS_FAILED; 177 return; 178 } 179 printf("thr #%d: compare frame #%d: fields are the same: " 180 " method: 0x%p, location: %#" LL "x\n", 181 ti, fi, fr1->method, fr1->location); 182 fflush(0); 183 } 184 } 185 186 void compare_one_stack_trace(int ti, 187 jvmtiStackInfo *stk1, 188 jvmtiStackInfo *stk2, 189 jvmtiThreadInfo *thr_info) 190 { 191 static const char* TEST_THREAD_NAME_PREFIX = "getallstktr001-"; 192 size_t PFX_LEN = strlen(TEST_THREAD_NAME_PREFIX); 193 194 if (thr_info->name != NULL) { 195 printf("compare stack #%d: thread: %s\n", ti, thr_info->name); 196 } else { 197 printf("compare stack #%d: thread is NULL\n", ti); 198 return; 199 } 200 201 if (strlen(thr_info->name) < PFX_LEN || 202 strncmp(thr_info->name, TEST_THREAD_NAME_PREFIX, PFX_LEN) != 0) 203 { 204 printf("compare stack #%d: %s isn't tested thread - skip it\n", 205 ti, thr_info->name); 206 return; 207 } 208 209 if (stk1->state != stk2->state) { 210 printf("FAILED: compare stack #%d: different states: " 211 "st1: %d, st2: %d\n", 212 ti, stk1->state, stk2->state); 213 iGlobalStatus = STATUS_FAILED; 214 return; 215 } 216 if (stk1->frame_count != stk2->frame_count) { 217 printf("FAILED: compare stack #%d: different frame_count: " 218 "cnt1: %d, cnt2: %d\n", 219 ti, stk1->frame_count, stk2->frame_count); 220 iGlobalStatus = STATUS_FAILED; 221 return; 222 } 223 224 printf("compare stack #%d: fields are the same: " 225 " jthread: 0x%p, state: %d, frame_count: %d\n", 226 ti, stk1->thread, stk1->state, stk1->frame_count); 227 228 fflush(0); 229 compare_all_frames(ti, 230 stk1->frame_count, 231 stk1->frame_buffer, 232 stk2->frame_buffer); 233 } 234 235 void compare_all_stack_traces(int thr_count, 236 jvmtiStackInfo *stk_buf1, 237 jvmtiStackInfo *stk_buf2, 238 jvmtiThreadInfo *thr_info) 239 { 240 int ti; 241 for (ti = 0; ti < thr_count; ti++) { 242 compare_one_stack_trace(ti, &stk_buf1[ti], &stk_buf2[ti], &thr_info[ti]); 243 } 244 } 245 246 247 JNIEXPORT void JNICALL 248 Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_GetAllStackTraces( 249 JNIEnv * env, jclass cls) 250 { 251 jvmtiError ret; 252 int ti; 253 254 ret = jvmti->GetAllStackTraces(MAX_FRAMES_CNT, &stack_buf1, &threads_count); 255 if (ret != JVMTI_ERROR_NONE) { 256 printf("Error: GetAllStackTraces %d \n", ret); 257 iGlobalStatus = STATUS_FAILED; 258 } 259 260 ret = jvmti->Allocate(sizeof(jthread) * threads_count, 261 (unsigned char**) &thread_list); 262 if (ret != JVMTI_ERROR_NONE) { 263 printf("Error: Allocate failed with %d \n", ret); 264 iGlobalStatus = STATUS_FAILED; 265 } 266 267 for (ti = 0; ti < threads_count; ti++) { 268 thread_list[ti] = 269 (jthread)env->NewGlobalRef(stack_buf1[ti].thread); 270 } 271 } 272 273 JNIEXPORT void JNICALL 274 Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_GetThreadsInfo( 275 JNIEnv * env, jclass cls) 276 { 277 jvmtiError ret; 278 int ti; 279 280 ret = jvmti->Allocate(sizeof(jvmtiThreadInfo) * threads_count, 281 (unsigned char**)&thread_info); 282 if (ret != JVMTI_ERROR_NONE) { 283 printf("Error: Allocate failed with %d \n", ret); 284 iGlobalStatus = STATUS_FAILED; 285 } 286 287 for (ti = 0; ti < threads_count; ti++) { 288 ret = jvmti->GetThreadInfo(thread_list[ti], &thread_info[ti]); 289 if (ret != JVMTI_ERROR_NONE) { 290 printf("Error: GetThreadInfo %d \n", ret); 291 iGlobalStatus = STATUS_FAILED; 292 } 293 printf("GetThreadInfo %d: thread: %s\n", ti, thread_info[ti].name); 294 fflush(0); 295 } 296 } 297 298 JNIEXPORT void JNICALL 299 Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_GetThreadListStackTraces( 300 JNIEnv * env, jclass cls) 301 { 302 jvmtiError ret; 303 304 ret = jvmti->GetThreadListStackTraces( 305 threads_count, thread_list, MAX_FRAMES_CNT, &stack_buf2); 306 if (ret != JVMTI_ERROR_NONE) { 307 printf("Error: GetThreadListStackTraces %d \n", ret); 308 iGlobalStatus = STATUS_FAILED; 309 } 310 311 } 312 313 JNIEXPORT void JNICALL 314 Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_ForceGC( 315 JNIEnv * env, jclass cls) 316 { 317 jvmtiError ret; 318 ret = jvmti->ForceGarbageCollection(); 319 320 if (ret != JVMTI_ERROR_NONE) { 321 printf("Error: ForceGarbageCollection %d \n", ret); 322 iGlobalStatus = STATUS_FAILED; 323 } 324 } 325 326 JNIEXPORT void JNICALL 327 Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_CompareStackTraces( 328 JNIEnv * env, jclass cls) 329 { 330 compare_all_stack_traces(threads_count, stack_buf1, stack_buf2, thread_info); 331 } 332 333 JNIEXPORT void JNICALL 334 Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_DeallocateBuffers( 335 JNIEnv * env, jclass cls) 336 { 337 jvmtiError ret; 338 339 ret = jvmti->Deallocate((unsigned char *) stack_buf1); 340 if (ret != JVMTI_ERROR_NONE) { 341 printf("Error: Deallocate stack_buf1 failed with %d \n", ret); 342 iGlobalStatus = STATUS_FAILED; 343 } 344 345 ret = jvmti->Deallocate((unsigned char *) stack_buf2); 346 if (ret != JVMTI_ERROR_NONE) { 347 printf("Error: Deallocate stack_buf2 failed with %d \n", ret); 348 iGlobalStatus = STATUS_FAILED; 349 } 350 351 ret = jvmti->Deallocate((unsigned char *) thread_info); 352 if (ret != JVMTI_ERROR_NONE) { 353 printf("Error: Deallocate thread_info failed with %d \n", ret); 354 iGlobalStatus = STATUS_FAILED; 355 } 356 ret = jvmti->Deallocate((unsigned char *) thread_list); 357 if (ret != JVMTI_ERROR_NONE) { 358 printf("Error: Deallocate thread_list failed with %d \n", ret); 359 iGlobalStatus = STATUS_FAILED; 360 } 361 } 362 363 }