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 objectCount = 0;
  37 static int userData = 0, allocationError = 0;
  38 
  39 static jvmtiEnv* st_jvmti = NULL;
  40 static const char* debugeeClassSignature = "Lnsk/jvmti/IterateOverObjectsReachableFromObject/iterobjreachobj002;";
  41 static const char* objectFieldName = "object";
  42 
  43 typedef struct ObjectDescStruct {
  44     jlong tag;
  45     jlong size;
  46 } ObjectDesc;
  47 
  48 static ObjectDesc *objectDescBuf;
  49 
  50 /* ============================================================================= */
  51 
  52 /* ============================================================================= */
  53 
  54 
  55 /** jvmtiObjectReferenceCallback for first iteration. */
  56 jvmtiIterationControl JNICALL
  57 objectReferenceCallback1( jvmtiObjectReferenceKind reference_kind,
  58                           jlong  class_tag,
  59                           jlong  size,
  60                           jlong* tag_ptr,
  61                           jlong  referrer_tag,
  62                           jint   referrer_index,
  63                           void*  user_data) {
  64 
  65     objectCount++;
  66     /* Set tag */
  67     *tag_ptr = objectCount;
  68 
  69     if (!NSK_JVMTI_VERIFY(st_jvmti->Allocate((sizeof(ObjectDesc)),
  70                                              (unsigned char**)&objectDescBuf))) {
  71         nsk_jvmti_setFailStatus();
  72         allocationError = 1;
  73     }
  74 
  75     (*objectDescBuf).tag = *tag_ptr;
  76     (*objectDescBuf).size = size;
  77 
  78     return JVMTI_ITERATION_ABORT;
  79 }
  80 
  81 /** jvmtiObjectReferenceCallback for second iteration. */
  82 jvmtiIterationControl JNICALL
  83 objectReferenceCallback2( jvmtiObjectReferenceKind reference_kind,
  84                           jlong  class_tag,
  85                           jlong  size,
  86                           jlong* tag_ptr,
  87                           jlong  referrer_tag,
  88                           jint   referrer_index,
  89                           void*  user_data) {
  90 
  91     objectCount--;
  92 
  93     if (!NSK_JVMTI_VERIFY(st_jvmti->Deallocate((unsigned char*)objectDescBuf))) {
  94         nsk_jvmti_setFailStatus();
  95     }
  96 
  97     return JVMTI_ITERATION_ABORT;
  98 }
  99 
 100 /* ============================================================================= */
 101 
 102 /** Agent algorithm. */
 103 static void JNICALL
 104 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
 105 
 106     NSK_DISPLAY0("Wait for debugee start\n");
 107     if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
 108         return;
 109 
 110     {
 111         jclass debugeeClass = NULL;
 112         jfieldID objectField = NULL;
 113         jobject object = NULL;
 114 
 115         do {
 116             NSK_DISPLAY1("Find debugee class: %s\n", debugeeClassSignature);
 117             debugeeClass = nsk_jvmti_classBySignature(debugeeClassSignature);
 118             if (debugeeClass == NULL) {
 119                 nsk_jvmti_setFailStatus();
 120                 break;
 121             }
 122 
 123             NSK_DISPLAY1("Find static field in debugee class: %s\n", objectFieldName);
 124             if (!NSK_JNI_VERIFY(jni, (objectField = jni->GetStaticFieldID(
 125                     debugeeClass, objectFieldName, debugeeClassSignature)) != NULL)) {
 126                 nsk_jvmti_setFailStatus();
 127                 break;
 128             }
 129 
 130             NSK_DISPLAY1("Find value of static field in debugee class: %s\n", objectFieldName);
 131             if (!NSK_JNI_VERIFY(jni, (object =
 132                     jni->GetStaticObjectField(debugeeClass, objectField)) != NULL)) {
 133                 nsk_jvmti_setFailStatus();
 134                 break;
 135             }
 136 
 137             NSK_DISPLAY0("Calling IterateOverObjectsReachableFromObject with allocation\n");
 138             {
 139                 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverObjectsReachableFromObject(
 140                         object, objectReferenceCallback1, &userData))) {
 141                     nsk_jvmti_setFailStatus();
 142                     break;
 143                 }
 144             }
 145 
 146             if (objectCount == 0) {
 147                 NSK_COMPLAIN0("First IterateOverObjectsReachableFromObject call had not visited any object\n");
 148                 nsk_jvmti_setFailStatus();
 149                 break;
 150             }
 151 
 152             if (allocationError) break;
 153 
 154             NSK_DISPLAY0("Calling IterateOverObjectsReachableFromObject with deallocation\n");
 155             {
 156                 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverObjectsReachableFromObject(
 157                         object, objectReferenceCallback2, &userData))) {
 158                     nsk_jvmti_setFailStatus();
 159                     break;
 160                 }
 161             }
 162 
 163             if (objectCount > 0) {
 164                 NSK_COMPLAIN0("Second IterateOverObjectsReachableFromObject call had not visited any object\n");
 165                 nsk_jvmti_setFailStatus();
 166             }
 167 
 168         } while (0);
 169     }
 170 
 171     NSK_DISPLAY0("Let debugee to finish\n");
 172     if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
 173         return;
 174 }
 175 
 176 /* ============================================================================= */
 177 
 178 /* ============================================================================= */
 179 
 180 /** Agent library initialization. */
 181 #ifdef STATIC_BUILD
 182 JNIEXPORT jint JNICALL Agent_OnLoad_iterobjreachobj002(JavaVM *jvm, char *options, void *reserved) {
 183     return Agent_Initialize(jvm, options, reserved);
 184 }
 185 JNIEXPORT jint JNICALL Agent_OnAttach_iterobjreachobj002(JavaVM *jvm, char *options, void *reserved) {
 186     return Agent_Initialize(jvm, options, reserved);
 187 }
 188 JNIEXPORT jint JNI_OnLoad_iterobjreachobj002(JavaVM *jvm, char *options, void *reserved) {
 189     return JNI_VERSION_1_8;
 190 }
 191 #endif
 192 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 193     jvmtiEnv* jvmti = NULL;
 194 
 195     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 196         return JNI_ERR;
 197 
 198     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
 199 
 200     if (!NSK_VERIFY((jvmti =
 201             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
 202         return JNI_ERR;
 203 
 204     /* save pointer to environment to use it in callbacks */
 205     st_jvmti = jvmti;
 206 
 207     {
 208         jvmtiCapabilities caps;
 209 
 210         memset(&caps, 0, sizeof(caps));
 211         caps.can_tag_objects = 1;
 212         if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {
 213             return JNI_ERR;
 214         }
 215     }
 216 
 217     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
 218         return JNI_ERR;
 219 
 220     return JNI_OK;
 221 }
 222 
 223 /* ============================================================================= */
 224 
 225 }