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 <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 static jlong timeout = 0; 35 36 static long objCounter = 0; 37 static int userData = 0; 38 static jvmtiEnv* st_jvmti = NULL; 39 static jlong nanos = 0; 40 static jvmtiTimerInfo timer_info1, timer_info2; 41 42 /* ============================================================================= */ 43 44 /* jvmtiHeapRootCallback */ 45 jvmtiIterationControl JNICALL 46 heapRootCallback( jvmtiHeapRootKind root_kind, 47 jlong class_tag, 48 jlong size, 49 jlong* tag_ptr, 50 void* user_data) { 51 52 *tag_ptr = (jlong)++objCounter; 53 54 if (!nsk_jvmti_isFailStatus()) { 55 56 if (!NSK_JVMTI_VERIFY(st_jvmti->GetCurrentThreadCpuTimerInfo(&timer_info1))) { 57 nsk_jvmti_setFailStatus(); 58 } 59 /* Check the returned jvmtiTimerInfo structure */ 60 if (timer_info1.max_value == 0) { 61 NSK_COMPLAIN0("heapRootCallback: GetCurrentThreadCpuTimerInfo returned zero in jvmtiTimerInfo.max_value\n"); 62 nsk_jvmti_setFailStatus(); 63 } 64 if (timer_info1.may_skip_forward != JNI_TRUE && timer_info1.may_skip_forward != JNI_FALSE) { 65 NSK_COMPLAIN0("heapRootCallback: GetCurrentThreadCpuTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_forward\n"); 66 nsk_jvmti_setFailStatus(); 67 } 68 if (timer_info1.may_skip_backward != JNI_TRUE && timer_info1.may_skip_backward != JNI_FALSE) { 69 NSK_COMPLAIN0("heapRootCallback: GetCurrentThreadCpuTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_backward\n"); 70 nsk_jvmti_setFailStatus(); 71 } 72 /* ---------------------------------------------------------------------- */ 73 74 if (!NSK_JVMTI_VERIFY(st_jvmti->GetCurrentThreadCpuTime(&nanos))) { 75 nsk_jvmti_setFailStatus(); 76 } 77 /* ---------------------------------------------------------------------- */ 78 79 if (!NSK_JVMTI_VERIFY(st_jvmti->GetTimerInfo(&timer_info2))) { 80 nsk_jvmti_setFailStatus(); 81 } 82 /* Check the returned jvmtiTimerInfo structure */ 83 if (timer_info2.max_value == 0) { 84 NSK_COMPLAIN0("heapRootCallback: GetTimerInfo returned zero in jvmtiTimerInfo.max_value\n"); 85 nsk_jvmti_setFailStatus(); 86 } 87 if (timer_info2.may_skip_forward != JNI_TRUE && timer_info2.may_skip_forward != JNI_FALSE) { 88 NSK_COMPLAIN0("heapRootCallback: GetTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_forward\n"); 89 nsk_jvmti_setFailStatus(); 90 } 91 if (timer_info2.may_skip_backward != JNI_TRUE && timer_info2.may_skip_backward != JNI_FALSE) { 92 NSK_COMPLAIN0("heapRootCallback: GetTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_backward\n"); 93 nsk_jvmti_setFailStatus(); 94 } 95 /* ---------------------------------------------------------------------- */ 96 97 nanos = 0; 98 if (!NSK_JVMTI_VERIFY(st_jvmti->GetTime(&nanos))) { 99 nsk_jvmti_setFailStatus(); 100 } 101 } 102 103 /* 104 NSK_DISPLAY1("heapRootCallback: %d\n", objCounter); 105 */ 106 return JVMTI_ITERATION_CONTINUE; 107 } 108 109 /* jvmtiStackReferenceCallback */ 110 jvmtiIterationControl JNICALL 111 stackReferenceCallback( jvmtiHeapRootKind root_kind, 112 jlong class_tag, 113 jlong size, 114 jlong* tag_ptr, 115 jlong thread_tag, 116 jint depth, 117 jmethodID method, 118 jint slot, 119 void* user_data) { 120 121 *tag_ptr = (jlong)++objCounter; 122 123 if (!nsk_jvmti_isFailStatus()) { 124 125 if (!NSK_JVMTI_VERIFY(st_jvmti->GetCurrentThreadCpuTimerInfo(&timer_info1))) { 126 nsk_jvmti_setFailStatus(); 127 } 128 /* Check the returned jvmtiTimerInfo structure */ 129 if (timer_info1.max_value == 0) { 130 NSK_COMPLAIN0("stackReferenceCallback: GetCurrentThreadCpuTimerInfo returned zero in jvmtiTimerInfo.max_value\n"); 131 nsk_jvmti_setFailStatus(); 132 } 133 if (timer_info1.may_skip_forward != JNI_TRUE && timer_info1.may_skip_forward != JNI_FALSE) { 134 NSK_COMPLAIN0("stackReferenceCallback: GetCurrentThreadCpuTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_forward\n"); 135 nsk_jvmti_setFailStatus(); 136 } 137 if (timer_info1.may_skip_backward != JNI_TRUE && timer_info1.may_skip_backward != JNI_FALSE) { 138 NSK_COMPLAIN0("stackReferenceCallback: GetCurrentThreadCpuTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_backward\n"); 139 nsk_jvmti_setFailStatus(); 140 } 141 /* ---------------------------------------------------------------------- */ 142 143 if (!NSK_JVMTI_VERIFY(st_jvmti->GetCurrentThreadCpuTime(&nanos))) { 144 nsk_jvmti_setFailStatus(); 145 } 146 /* ---------------------------------------------------------------------- */ 147 148 if (!NSK_JVMTI_VERIFY(st_jvmti->GetTimerInfo(&timer_info2))) { 149 nsk_jvmti_setFailStatus(); 150 } 151 /* Check the returned jvmtiTimerInfo structure */ 152 if (timer_info2.max_value == 0) { 153 NSK_COMPLAIN0("stackReferenceCallback: GetTimerInfo returned zero in jvmtiTimerInfo.max_value\n"); 154 nsk_jvmti_setFailStatus(); 155 } 156 if (timer_info2.may_skip_forward != JNI_TRUE && timer_info2.may_skip_forward != JNI_FALSE) { 157 NSK_COMPLAIN0("stackReferenceCallback: GetTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_forward\n"); 158 nsk_jvmti_setFailStatus(); 159 } 160 if (timer_info2.may_skip_backward != JNI_TRUE && timer_info2.may_skip_backward != JNI_FALSE) { 161 NSK_COMPLAIN0("stackReferenceCallback: GetTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_backward\n"); 162 nsk_jvmti_setFailStatus(); 163 } 164 /* ---------------------------------------------------------------------- */ 165 166 nanos = 0; 167 if (!NSK_JVMTI_VERIFY(st_jvmti->GetTime(&nanos))) { 168 nsk_jvmti_setFailStatus(); 169 } 170 } 171 172 /* 173 NSK_DISPLAY1("stackRefenceCallback: %d\n", objCounter); 174 */ 175 return JVMTI_ITERATION_CONTINUE; 176 } 177 178 179 /* jvmtiObjectReferenceCallback */ 180 jvmtiIterationControl JNICALL 181 objectReferenceCallback( jvmtiObjectReferenceKind reference_kind, 182 jlong class_tag, 183 jlong size, 184 jlong* tag_ptr, 185 jlong referrer_tag, 186 jint referrer_index, 187 void* user_data) { 188 189 *tag_ptr = (jlong)++objCounter; 190 191 if (!NSK_JVMTI_VERIFY(st_jvmti->GetCurrentThreadCpuTimerInfo(&timer_info1))) { 192 nsk_jvmti_setFailStatus(); 193 } 194 /* Check the returned jvmtiTimerInfo structure */ 195 if (timer_info1.max_value == 0) { 196 NSK_COMPLAIN0("objectReferenceCallback: GetCurrentThreadCpuTimerInfo returned zero in jvmtiTimerInfo.max_value\n"); 197 nsk_jvmti_setFailStatus(); 198 } 199 if (timer_info1.may_skip_forward != JNI_TRUE && timer_info1.may_skip_forward != JNI_FALSE) { 200 NSK_COMPLAIN0("objectReferenceCallback: GetCurrentThreadCpuTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_forward\n"); 201 nsk_jvmti_setFailStatus(); 202 } 203 if (timer_info1.may_skip_backward != JNI_TRUE && timer_info1.may_skip_backward != JNI_FALSE) { 204 NSK_COMPLAIN0("objectReferenceCallback: GetCurrentThreadCpuTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_backward\n"); 205 nsk_jvmti_setFailStatus(); 206 } 207 /* ---------------------------------------------------------------------- */ 208 209 if (!NSK_JVMTI_VERIFY(st_jvmti->GetCurrentThreadCpuTime(&nanos))) { 210 nsk_jvmti_setFailStatus(); 211 } 212 /* ---------------------------------------------------------------------- */ 213 214 215 if (!NSK_JVMTI_VERIFY(st_jvmti->GetTimerInfo(&timer_info2))) { 216 nsk_jvmti_setFailStatus(); 217 } 218 /* Check the returned jvmtiTimerInfo structure */ 219 if (timer_info2.max_value == 0) { 220 NSK_COMPLAIN0("objectReferenceCallback: GetTimerInfo returned zero in jvmtiTimerInfo.max_value\n"); 221 nsk_jvmti_setFailStatus(); 222 } 223 if (timer_info2.may_skip_forward != JNI_TRUE && timer_info2.may_skip_forward != JNI_FALSE) { 224 NSK_COMPLAIN0("objectReferenceCallback: GetTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_forward\n"); 225 nsk_jvmti_setFailStatus(); 226 } 227 if (timer_info2.may_skip_backward != JNI_TRUE && timer_info2.may_skip_backward != JNI_FALSE) { 228 NSK_COMPLAIN0("objectReferenceCallback: GetTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_backward\n"); 229 nsk_jvmti_setFailStatus(); 230 } 231 /* ---------------------------------------------------------------------- */ 232 233 nanos = 0; 234 if (!NSK_JVMTI_VERIFY(st_jvmti->GetTime(&nanos))) { 235 nsk_jvmti_setFailStatus(); 236 } 237 238 NSK_DISPLAY1("objectRefenceCallback: %d\n", objCounter); 239 return JVMTI_ITERATION_ABORT; 240 } 241 242 /* ============================================================================= */ 243 244 /** Agent algorithm. */ 245 static void JNICALL 246 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 247 248 NSK_DISPLAY0("Wait for debugee start\n"); 249 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 250 return; 251 252 { 253 do { 254 NSK_DISPLAY0("Calling IterateOverReachableObjects\n"); 255 { 256 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverReachableObjects(heapRootCallback, 257 stackReferenceCallback, 258 objectReferenceCallback, 259 &userData))) { 260 nsk_jvmti_setFailStatus(); 261 break; 262 } 263 } 264 265 if (objCounter == 0) { 266 NSK_COMPLAIN0("IterateOverReachableObjects call had not visited any object\n"); 267 nsk_jvmti_setFailStatus(); 268 break; 269 } else { 270 NSK_DISPLAY1("Number of objects the IterateOverReachableObjects visited: %d\n", objCounter); 271 } 272 273 } while (0); 274 } 275 276 NSK_DISPLAY0("Let debugee to finish\n"); 277 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 278 return; 279 } 280 281 /* ============================================================================= */ 282 283 /* ============================================================================= */ 284 285 /** Agent library initialization. */ 286 #ifdef STATIC_BUILD 287 JNIEXPORT jint JNICALL Agent_OnLoad_iterreachobj005(JavaVM *jvm, char *options, void *reserved) { 288 return Agent_Initialize(jvm, options, reserved); 289 } 290 JNIEXPORT jint JNICALL Agent_OnAttach_iterreachobj005(JavaVM *jvm, char *options, void *reserved) { 291 return Agent_Initialize(jvm, options, reserved); 292 } 293 JNIEXPORT jint JNI_OnLoad_iterreachobj005(JavaVM *jvm, char *options, void *reserved) { 294 return JNI_VERSION_1_8; 295 } 296 #endif 297 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 298 jvmtiEnv* jvmti = NULL; 299 300 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 301 return JNI_ERR; 302 303 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 304 305 if (!NSK_VERIFY((jvmti = 306 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 307 return JNI_ERR; 308 309 /* save pointer to environment to use it in callbacks */ 310 st_jvmti = jvmti; 311 312 { 313 jvmtiCapabilities caps; 314 315 memset(&caps, 0, sizeof(caps)); 316 caps.can_tag_objects = 1; 317 caps.can_get_current_thread_cpu_time = 1; 318 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) { 319 return JNI_ERR; 320 } 321 } 322 323 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 324 return JNI_ERR; 325 326 return JNI_OK; 327 } 328 329 /* ============================================================================= */ 330 331 }