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 PASSED  0
  37 #define STATUS_FAILED  2
  38 
  39 #define TESTED_CLASS "ap02t001Exception"
  40 
  41 static JNIEnv *jni = NULL;
  42 static jvmtiEnv *jvmti = NULL;
  43 static jvmtiEventCallbacks callbacks;
  44 static jvmtiCapabilities caps;
  45 
  46 static volatile int obj_count = 0;
  47 static int first_count = 0;
  48 
  49 static jlong timeout = 0;
  50 static int user_data = 0;
  51 static const char* TESTED_CLASS_SIGNATURE = "Lnsk/jvmti/scenarios/allocation/AP02/ap02t001Exception;";
  52 static const jlong TESTED_CLASS_TAG = (jlong)1024;
  53 static jclass testedClass = NULL;
  54 
  55 jvmtiIterationControl JNICALL
  56 heapObjectCallback(jlong class_tag,
  57                    jlong size,
  58                    jlong* tag_ptr,
  59                    void* user_data) {
  60 
  61     if (class_tag == TESTED_CLASS_TAG) {
  62         obj_count++;
  63     }
  64 
  65     return JVMTI_ITERATION_CONTINUE;
  66 }
  67 
  68 jvmtiIterationControl JNICALL
  69 stackReferenceCallback( jvmtiHeapRootKind root_kind,
  70                         jlong     class_tag,
  71                         jlong     size,
  72                         jlong*    tag_ptr,
  73                         jlong     thread_tag,
  74                         jint      depth,
  75                         jmethodID method,
  76                         jint      slot,
  77                         void*     user_data) {
  78 
  79     if (class_tag == TESTED_CLASS_TAG) {
  80         obj_count++;
  81     }
  82 
  83     return JVMTI_ITERATION_CONTINUE;
  84 }
  85 
  86 /************************/
  87 
  88 JNIEXPORT void JNICALL
  89 Java_nsk_jvmti_scenarios_allocation_AP02_ap02t001_throwException( JNIEnv* jni,
  90                                                                   jclass cls,
  91                                                                   jclass exception_cls ) {
  92     jint result;
  93 
  94     result = jni->ThrowNew(exception_cls, "Got expected exception thrown from native code" );
  95     if (result != 0) {
  96         NSK_COMPLAIN1("throwException: Unable to throw exception in native code: %d\n\n", result );
  97         nsk_jvmti_setFailStatus();
  98     } else {
  99         NSK_DISPLAY0("throwException: ThrowNew returned success code: 0\n\n");
 100     }
 101 }
 102 
 103 static void runIterations (jvmtiEnv* jvmti, jclass testedClass, jint exp_count) {
 104     NSK_DISPLAY0("Calling IterateOverInstancesOfClass with filter JVMTI_HEAP_OBJECT_EITHER\n");
 105     obj_count = 0;
 106     if (!NSK_JVMTI_VERIFY(jvmti->IterateOverInstancesOfClass(testedClass,
 107                                                              JVMTI_HEAP_OBJECT_EITHER,
 108                                                              heapObjectCallback,
 109                                                              &user_data))) {
 110         nsk_jvmti_setFailStatus();
 111         return;
 112     }
 113 
 114     if (obj_count != exp_count) {
 115         nsk_jvmti_setFailStatus();
 116         NSK_COMPLAIN3(
 117             "IterateOverInstancesOfClass found unexpected number of %s objects: %d\n"
 118             "\texpected number: %d\n\n",
 119             TESTED_CLASS, obj_count, exp_count);
 120     } else {
 121         NSK_DISPLAY2("Number of %s objects IterateOverInstancesOfClass has found: %d\n\n", TESTED_CLASS,
 122             obj_count);
 123     }
 124 
 125     NSK_DISPLAY0("Calling IterateOverHeap with filter JVMTI_HEAP_OBJECT_EITHER\n");
 126     obj_count = 0;
 127     if (!NSK_JVMTI_VERIFY(
 128             jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_EITHER, heapObjectCallback, &user_data))) {
 129         nsk_jvmti_setFailStatus();
 130         return;
 131     }
 132 
 133     if (obj_count != exp_count) {
 134         nsk_jvmti_setFailStatus();
 135         NSK_COMPLAIN3(
 136             "IterateOverHeap found unexpected number of %s objects: %d\n"
 137             "\texpected number: %d\n\n",
 138             TESTED_CLASS, obj_count, exp_count);
 139     } else {
 140         NSK_DISPLAY2("Number of %s objects IterateOverHeap has found: %d\n\n", TESTED_CLASS, obj_count);
 141     }
 142 
 143     NSK_DISPLAY0("Calling IterateOverReachableObjects\n");
 144     obj_count = 0;
 145     if (!NSK_JVMTI_VERIFY(jvmti->IterateOverReachableObjects(NULL /*heapRootCallback*/,
 146                                                              stackReferenceCallback,
 147                                                              NULL /*objectReferenceCallback*/,
 148                                                              &user_data))) {
 149         nsk_jvmti_setFailStatus();
 150         return;
 151     }
 152 
 153     if (obj_count != exp_count) {
 154         nsk_jvmti_setFailStatus();
 155         NSK_COMPLAIN3(
 156             "IterateOverReachableObjects found unexpected number of %s objects: %d\n"
 157             "\texpected number: %d\n\n",
 158             TESTED_CLASS, obj_count, exp_count);
 159     } else {
 160         NSK_DISPLAY2("Number of %s objects IterateOverReachableObjects has found: %d\n\n", TESTED_CLASS,
 161             obj_count);
 162     }
 163 
 164     first_count = obj_count;
 165 }
 166 
 167 static void JNICALL
 168 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
 169 
 170     NSK_DISPLAY0("Wait for debugee start\n\n");
 171     if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
 172         return;
 173 
 174     NSK_DISPLAY1("Find tested class: %s\n", TESTED_CLASS_SIGNATURE);
 175     testedClass = nsk_jvmti_classBySignature(TESTED_CLASS_SIGNATURE);
 176     if (testedClass == NULL) {
 177         nsk_jvmti_setFailStatus();
 178         return;
 179     }
 180 
 181     if (!NSK_JNI_VERIFY(jni, (testedClass = (jclass)jni->NewGlobalRef(testedClass)) != NULL))
 182         return;
 183 
 184     NSK_DISPLAY0("Set tag for tested class\n\n");
 185     if (!NSK_JVMTI_VERIFY(jvmti->SetTag(testedClass, TESTED_CLASS_TAG))) {
 186         nsk_jvmti_setFailStatus();
 187         return;
 188     }
 189 
 190     runIterations (jvmti, testedClass, 1);
 191 
 192     NSK_DISPLAY0("Go to next case\n");
 193     if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
 194         return;
 195     if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
 196         return;
 197 
 198     runIterations (jvmti, testedClass, 2);
 199 
 200     NSK_TRACE(jni->DeleteGlobalRef(testedClass));
 201 
 202     NSK_DISPLAY0("Let debugee to finish\n");
 203     if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
 204         return;
 205 }
 206 
 207 #ifdef STATIC_BUILD
 208 JNIEXPORT jint JNICALL Agent_OnLoad_ap02t001(JavaVM *jvm, char *options, void *reserved) {
 209     return Agent_Initialize(jvm, options, reserved);
 210 }
 211 JNIEXPORT jint JNICALL Agent_OnAttach_ap02t001(JavaVM *jvm, char *options, void *reserved) {
 212     return Agent_Initialize(jvm, options, reserved);
 213 }
 214 JNIEXPORT jint JNI_OnLoad_ap02t001(JavaVM *jvm, char *options, void *reserved) {
 215     return JNI_VERSION_1_8;
 216 }
 217 #endif
 218 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 219     /* init framework and parse options */
 220     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 221         return JNI_ERR;
 222 
 223     /* create JVMTI environment */
 224     if (!NSK_VERIFY((jvmti =
 225             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
 226         return JNI_ERR;
 227 
 228     memset(&caps, 0, sizeof(jvmtiCapabilities));
 229     caps.can_tag_objects = 1;
 230     if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
 231         return JNI_ERR;
 232 
 233     if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps)))
 234         return JNI_ERR;
 235 
 236     if (!caps.can_tag_objects)
 237         NSK_DISPLAY0("Warning: tagging objects is not implemented\n");
 238 
 239     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
 240         return JNI_ERR;
 241     NSK_DISPLAY0("agentProc has been set\n\n");
 242 
 243     return JNI_OK;
 244 }
 245 
 246 }