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 }