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 <string.h>
  26 #include <jvmti.h>
  27 #include "agent_common.h"
  28 
  29 #include "nsk_tools.h"
  30 #include "jni_tools.h"
  31 #include "JVMTITools.h"
  32 #include "jvmti_tools.h"
  33 
  34 extern "C" {
  35 
  36 #define EXP_OBJ_NUMBER 1
  37 
  38 static JNIEnv *jni = NULL;
  39 static jvmtiEnv *jvmti = NULL;
  40 static jvmtiEventCallbacks callbacks;
  41 static jvmtiCapabilities caps;
  42 
  43 static jlong timeout = 0;
  44 static jobject referrer = NULL;
  45 static const char* SUBCLASS_SIGNATURE   = "Lnsk/jvmti/scenarios/allocation/AP05/ap05t002Subclass;";
  46 static const long  TAG1 = 1l, TAG2 = 2l;
  47 static int caseNumber = 0, forthRef = 0, backRef = 0;
  48 
  49 /* jvmtiHeapRootCallback */
  50 jvmtiIterationControl JNICALL
  51 heapRootCallback(jvmtiHeapRootKind root_kind,
  52                   jlong class_tag,
  53                   jlong size,
  54                   jlong* tag_ptr,
  55                   void* user_data) {
  56     return JVMTI_ITERATION_CONTINUE;
  57 }
  58 
  59 /* jvmtiStackReferenceCallback */
  60 jvmtiIterationControl JNICALL
  61 stackReferenceCallback(jvmtiHeapRootKind root_kind,
  62                        jlong     class_tag,
  63                        jlong     size,
  64                        jlong*    tag_ptr,
  65                        jlong     thread_tag,
  66                        jint      depth,
  67                        jmethodID method,
  68                        jint      slot,
  69                        void*     user_data) {
  70     return JVMTI_ITERATION_CONTINUE;
  71 }
  72 
  73 
  74 /* jvmtiObjectReferenceCallback */
  75 jvmtiIterationControl JNICALL
  76 objectReferenceCallback(jvmtiObjectReferenceKind reference_kind,
  77                         jlong  class_tag,
  78                         jlong  size,
  79                         jlong* tag_ptr,
  80                         jlong  referrer_tag,
  81                         jint   referrer_index,
  82                         void*  user_data) {
  83 
  84     if (*tag_ptr != 0 && referrer_tag != 0) {
  85         NSK_DISPLAY4("objectReferenceCallback: reference kind=%s, referrer_index=%d, referrer_tag=%d, referree_tag=%d\n",
  86             TranslateObjectRefKind(reference_kind), (int)referrer_index, (long)referrer_tag, (long)*tag_ptr);
  87 
  88         if (*tag_ptr == TAG1 && referrer_tag == TAG2) {
  89             forthRef++;
  90         } else if (*tag_ptr == TAG2 && referrer_tag == TAG1) {
  91             backRef++;
  92         }
  93     }
  94     return JVMTI_ITERATION_CONTINUE;
  95 }
  96 
  97 
  98 /************************/
  99 
 100 JNIEXPORT void JNICALL
 101 Java_nsk_jvmti_scenarios_allocation_AP05_ap05t002_setTag(JNIEnv* jni,
 102                                                          jobject obj,
 103                                                          jobject target,
 104                                                          jlong   tag) {
 105 
 106     if (!NSK_JVMTI_VERIFY(jvmti->SetTag(target, tag))) {
 107         nsk_jvmti_setFailStatus();
 108     }
 109 }
 110 
 111 JNIEXPORT void JNICALL
 112 Java_nsk_jvmti_scenarios_allocation_AP05_ap05t002_setReferrer(JNIEnv* jni, jclass klass, jobject ref, jint caseNum) {
 113     caseNumber = caseNum;
 114     if (!NSK_JNI_VERIFY(jni, (referrer = jni->NewGlobalRef(ref)) != NULL))
 115         nsk_jvmti_setFailStatus();
 116 }
 117 
 118 static void runCase() {
 119     NSK_DISPLAY0("\nCalling IterateOverReachableObjects\n");
 120     forthRef = 0;
 121     backRef = 0;
 122     if (!NSK_JVMTI_VERIFY(jvmti->IterateOverReachableObjects(heapRootCallback,
 123                                                              stackReferenceCallback,
 124                                                              objectReferenceCallback,
 125                                                              NULL /*user_data*/))) {
 126         nsk_jvmti_setFailStatus();
 127     }
 128     if (forthRef != 1) {
 129         NSK_COMPLAIN1("IterateOverReachableObjects found unexpected number of references\n\t"
 130               "from referrer to referree; found: %d, expected: 1\n\n", forthRef);
 131         nsk_jvmti_setFailStatus();
 132     }
 133     if (backRef != 1) {
 134         NSK_COMPLAIN1("IterateOverReachableObjects found unexpected number of references\n\t"
 135               "from referree to referrer; found: %d, expected: 1\n\n", backRef);
 136         nsk_jvmti_setFailStatus();
 137     }
 138 
 139     NSK_DISPLAY0("\nCalling IterateOverObjectsReachableFromObject\n");
 140     forthRef = 0;
 141     backRef = 0;
 142     if (!NSK_JVMTI_VERIFY(jvmti->IterateOverObjectsReachableFromObject(referrer,
 143                                                                        objectReferenceCallback,
 144                                                                        NULL /*user_data*/))) {
 145         nsk_jvmti_setFailStatus();
 146     }
 147     if (forthRef != 1) {
 148         NSK_COMPLAIN1("IterateOverObjectsReachableFromObject found unexpected number of references\n\t"
 149               "from referrer to referree; found: %d, expected: 1\n\n", forthRef);
 150         nsk_jvmti_setFailStatus();
 151     }
 152     if (backRef != 1) {
 153         NSK_COMPLAIN1("IterateOverObjectsReachableFromObject found unexpected number of references\n\t"
 154               "from referree to referrer; found: %d, expected: 1\n\n", backRef);
 155         nsk_jvmti_setFailStatus();
 156     }
 157 }
 158 
 159 static void JNICALL
 160 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
 161 
 162     jclass debugeeClass = NULL;
 163 
 164     NSK_DISPLAY0("Wait for debugee start\n\n");
 165     if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
 166         return;
 167 
 168     do {
 169         NSK_DISPLAY0("CASE #1\n");
 170         runCase();
 171 
 172         NSK_TRACE(jni->DeleteGlobalRef(referrer));
 173         if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
 174             return;
 175         if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
 176             return;
 177 
 178         NSK_DISPLAY0("CASE #2\n");
 179         runCase();
 180 
 181         NSK_TRACE(jni->DeleteGlobalRef(referrer));
 182     } while (0);
 183 
 184     NSK_DISPLAY0("Let debugee to finish\n");
 185     if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
 186         return;
 187 }
 188 
 189 #ifdef STATIC_BUILD
 190 JNIEXPORT jint JNICALL Agent_OnLoad_ap05t002(JavaVM *jvm, char *options, void *reserved) {
 191     return Agent_Initialize(jvm, options, reserved);
 192 }
 193 JNIEXPORT jint JNICALL Agent_OnAttach_ap05t002(JavaVM *jvm, char *options, void *reserved) {
 194     return Agent_Initialize(jvm, options, reserved);
 195 }
 196 JNIEXPORT jint JNI_OnLoad_ap05t002(JavaVM *jvm, char *options, void *reserved) {
 197     return JNI_VERSION_1_8;
 198 }
 199 #endif
 200 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 201     /* init framework and parse options */
 202     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 203         return JNI_ERR;
 204 
 205     /* create JVMTI environment */
 206     if (!NSK_VERIFY((jvmti =
 207             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
 208         return JNI_ERR;
 209 
 210     memset(&caps, 0, sizeof(jvmtiCapabilities));
 211     caps.can_tag_objects = 1;
 212 
 213     if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
 214         return JNI_ERR;
 215 
 216     if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps)))
 217         return JNI_ERR;
 218 
 219     if (!caps.can_tag_objects)
 220         NSK_DISPLAY0("Warning: tagging objects is not implemented\n");
 221 
 222     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
 223         return JNI_ERR;
 224     NSK_DISPLAY0("agentProc has been set\n\n");
 225 
 226     return JNI_OK;
 227 }
 228 
 229 }