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 <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <jvmti.h> 28 #include "agent_common.h" 29 30 #include "nsk_tools.h" 31 #include "jni_tools.h" 32 #include "JVMTITools.h" 33 #include "jvmti_tools.h" 34 35 extern "C" { 36 37 #define PASSED 0 38 #define STATUS_FAILED 2 39 40 #define EXP_OBJ_NUMBER 7 41 42 static JNIEnv *jni = NULL; 43 static jvmtiEnv *jvmti = NULL; 44 static jvmtiEventCallbacks callbacks; 45 static jvmtiCapabilities caps; 46 47 static volatile int obj_free = 0; 48 static volatile long obj_count = 0; 49 50 static jlong timeout = 0; 51 static int user_data = 0; 52 static const char* DEBUGEE_SIGNATURE = "Lnsk/jvmti/scenarios/allocation/AP01/ap01t001;"; 53 static const jlong DEBUGEE_CLASS_TAG = (jlong)1024; 54 55 void JNICALL 56 ObjectFree(jvmtiEnv *jvmti_env, jlong tag) { 57 NSK_DISPLAY1("ObjectFree event received for an object with tag %ld\n\n", (long)tag); 58 obj_free++; 59 } 60 61 void JNICALL 62 VMDeath(jvmtiEnv *jvmti_env, JNIEnv *env) { 63 64 NSK_DISPLAY0("VMDeath event received\n"); 65 66 if (obj_free != (EXP_OBJ_NUMBER - 1) ) { 67 NSK_COMPLAIN2( 68 "Received unexpected number of ObjectFree events: %d\n" 69 "\texpected number: %d\n", 70 obj_free, (EXP_OBJ_NUMBER - 1)); 71 exit(95 + STATUS_FAILED); 72 } 73 74 exit(95 + PASSED); 75 } 76 77 jvmtiIterationControl JNICALL 78 heapObjectCallback(jlong class_tag, 79 jlong size, 80 jlong* tag_ptr, 81 void* user_data) { 82 83 if (class_tag == DEBUGEE_CLASS_TAG) { 84 obj_count++; 85 } 86 87 return JVMTI_ITERATION_CONTINUE; 88 } 89 90 jvmtiIterationControl JNICALL 91 stackReferenceCallback( jvmtiHeapRootKind root_kind, 92 jlong class_tag, 93 jlong size, 94 jlong* tag_ptr, 95 jlong thread_tag, 96 jint depth, 97 jmethodID method, 98 jint slot, 99 void* user_data) { 100 101 if (class_tag == DEBUGEE_CLASS_TAG && *tag_ptr == 0) { 102 obj_count++; 103 *tag_ptr = obj_count; 104 } 105 106 return JVMTI_ITERATION_CONTINUE; 107 } 108 109 jvmtiIterationControl JNICALL 110 heapRootCallback( jvmtiHeapRootKind root_kind, 111 jlong class_tag, 112 jlong size, 113 jlong* tag_ptr, 114 void* user_data) { 115 116 if (class_tag == DEBUGEE_CLASS_TAG && *tag_ptr == 0) { 117 obj_count++; 118 *tag_ptr = obj_count; 119 } 120 121 return JVMTI_ITERATION_CONTINUE; 122 } 123 124 jvmtiIterationControl JNICALL 125 objectReferenceCallback( jvmtiObjectReferenceKind reference_kind, 126 jlong class_tag, 127 jlong size, 128 jlong* tag_ptr, 129 jlong referrer_tag, 130 jint referrer_index, 131 void* user_data) { 132 133 if (class_tag == DEBUGEE_CLASS_TAG && *tag_ptr == 0) { 134 obj_count++; 135 *tag_ptr = obj_count; 136 } 137 138 return JVMTI_ITERATION_CONTINUE; 139 } 140 141 142 /************************/ 143 144 JNIEXPORT jobject JNICALL 145 Java_nsk_jvmti_scenarios_allocation_AP01_ap01t001_newObject( JNIEnv* jni, jclass cls ) { 146 jmethodID cid; 147 jobject result; 148 149 if (!NSK_JNI_VERIFY(jni, (cid = jni->GetMethodID(cls, "<init>", "()V" )) != NULL)) { 150 NSK_COMPLAIN0("newObject: GetMethodID returned NULL\n\n"); 151 nsk_jvmti_setFailStatus(); 152 return NULL; 153 } 154 155 if (!NSK_JNI_VERIFY(jni, ( result = jni->NewObject(cls, cid)) != NULL)) { 156 157 NSK_COMPLAIN0("newObject: NewObject returned NULL\n\n"); 158 nsk_jvmti_setFailStatus(); 159 return NULL; 160 } 161 162 return result; 163 } 164 165 JNIEXPORT jobject JNICALL 166 Java_nsk_jvmti_scenarios_allocation_AP01_ap01t001_allocObject( JNIEnv* jni, jclass cls ) { 167 jmethodID cid; 168 jobject result; 169 170 if (!NSK_JNI_VERIFY(jni, ( cid = jni->GetMethodID(cls, "<init>", "()V" )) != NULL)) { 171 172 NSK_COMPLAIN0("allocObject: GetMethodID returned NULL\n\n"); 173 nsk_jvmti_setFailStatus(); 174 return NULL; 175 } 176 177 if (!NSK_JNI_VERIFY(jni, ( result = jni->AllocObject(cls)) != NULL)) { 178 179 NSK_COMPLAIN0("allocObject: AllocObject returned NULL\n\n"); 180 nsk_jvmti_setFailStatus(); 181 return NULL; 182 } 183 184 if (!NSK_JNI_VERIFY_VOID(jni,jni->CallNonvirtualVoidMethod(result, cls, cid))) { 185 186 NSK_COMPLAIN0("newObject: CallNonvirtualVoidMethod failed\n\n"); 187 nsk_jvmti_setFailStatus(); 188 return NULL; 189 } 190 191 return result; 192 } 193 194 static void JNICALL 195 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 196 197 jclass debugeeClass = NULL; 198 199 NSK_DISPLAY0("Wait for debugee start\n\n"); 200 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 201 return; 202 203 NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_SIGNATURE); 204 debugeeClass = nsk_jvmti_classBySignature(DEBUGEE_SIGNATURE); 205 if (debugeeClass == NULL) { 206 nsk_jvmti_setFailStatus(); 207 return; 208 } 209 210 NSK_DISPLAY0("Set tag for debugee class\n\n"); 211 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(debugeeClass, DEBUGEE_CLASS_TAG))) { 212 nsk_jvmti_setFailStatus(); 213 return; 214 } 215 216 217 NSK_DISPLAY0("Calling IterateOverInstancesOfClass with filter JVMTI_HEAP_OBJECT_UNTAGGED\n"); 218 obj_count = 0; 219 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverInstancesOfClass(debugeeClass, 220 JVMTI_HEAP_OBJECT_UNTAGGED, 221 heapObjectCallback, 222 &user_data))) { 223 nsk_jvmti_setFailStatus(); 224 return; 225 } 226 227 if (obj_count != EXP_OBJ_NUMBER) { 228 nsk_jvmti_setFailStatus(); 229 NSK_COMPLAIN2( 230 "IterateOverInstancesOfClass found unexpected number of objects: %d\n" 231 "\texpected number: %d\n\n", 232 obj_count, EXP_OBJ_NUMBER); 233 234 } else { 235 NSK_DISPLAY1("Number of objects IterateOverInstancesOfClass has found: %d\n\n", obj_count); 236 } 237 238 NSK_DISPLAY0("Calling IterateOverHeap with filter JVMTI_HEAP_OBJECT_UNTAGGED\n"); 239 obj_count = 0; 240 if (!NSK_JVMTI_VERIFY( 241 jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_UNTAGGED, heapObjectCallback, &user_data))) { 242 nsk_jvmti_setFailStatus(); 243 return; 244 } 245 246 if (obj_count != EXP_OBJ_NUMBER) { 247 nsk_jvmti_setFailStatus(); 248 NSK_COMPLAIN2( 249 "IterateOverHeap found unexpected number of objects: %d\n" 250 "\texpected number: %d\n\n", 251 obj_count, EXP_OBJ_NUMBER); 252 } else { 253 NSK_DISPLAY1("Number of objects IterateOverHeap has found: %d\n\n", obj_count); 254 } 255 256 NSK_DISPLAY0("Calling IterateOverReachableObjects\n"); 257 obj_count = 0; 258 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverReachableObjects(heapRootCallback, 259 stackReferenceCallback, 260 objectReferenceCallback, 261 &user_data))) { 262 nsk_jvmti_setFailStatus(); 263 return; 264 } 265 266 if (obj_count != EXP_OBJ_NUMBER) { 267 nsk_jvmti_setFailStatus(); 268 NSK_COMPLAIN2( 269 "IterateOverReachableObjects found unexpected number of objects: %d\n" 270 "\texpected number: %d\n\n", 271 obj_count, EXP_OBJ_NUMBER); 272 } else { 273 NSK_DISPLAY1("Number of objects IterateOverReachableObjects has found: %d\n\n", obj_count); 274 } 275 276 NSK_DISPLAY0("Let debugee to provoke GC\n"); 277 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 278 return; 279 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 280 return; 281 282 283 NSK_DISPLAY0("Let debugee to finish\n"); 284 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 285 return; 286 } 287 288 #ifdef STATIC_BUILD 289 JNIEXPORT jint JNICALL Agent_OnLoad_ap01t001(JavaVM *jvm, char *options, void *reserved) { 290 return Agent_Initialize(jvm, options, reserved); 291 } 292 JNIEXPORT jint JNICALL Agent_OnAttach_ap01t001(JavaVM *jvm, char *options, void *reserved) { 293 return Agent_Initialize(jvm, options, reserved); 294 } 295 JNIEXPORT jint JNI_OnLoad_ap01t001(JavaVM *jvm, char *options, void *reserved) { 296 return JNI_VERSION_1_8; 297 } 298 #endif 299 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 300 /* init framework and parse options */ 301 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 302 return JNI_ERR; 303 304 /* create JVMTI environment */ 305 if (!NSK_VERIFY((jvmti = 306 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 307 return JNI_ERR; 308 309 memset(&caps, 0, sizeof(jvmtiCapabilities)); 310 caps.can_generate_object_free_events = 1; 311 caps.can_tag_objects = 1; 312 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) 313 return JNI_ERR; 314 315 if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps))) 316 return JNI_ERR; 317 318 if (!caps.can_generate_object_free_events) 319 NSK_DISPLAY0("Warning: generation of object free events is not implemented\n"); 320 if (!caps.can_tag_objects) 321 NSK_DISPLAY0("Warning: tagging objects is not implemented\n"); 322 323 /* set event callback */ 324 NSK_DISPLAY0("setting event callbacks ...\n"); 325 (void) memset(&callbacks, 0, sizeof(callbacks)); 326 327 callbacks.ObjectFree = &ObjectFree; 328 callbacks.VMDeath = &VMDeath; 329 330 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)))) 331 return JNI_ERR; 332 333 NSK_DISPLAY0("setting event callbacks done\nenabling JVMTI events ...\n"); 334 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, 335 JVMTI_EVENT_OBJECT_FREE, 336 NULL))) 337 return JNI_ERR; 338 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, 339 JVMTI_EVENT_VM_DEATH, 340 NULL))) 341 return JNI_ERR; 342 NSK_DISPLAY0("enabling the events done\n\n"); 343 344 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 345 return JNI_ERR; 346 NSK_DISPLAY0("agentProc has been set\n\n"); 347 348 return JNI_OK; 349 } 350 351 }