1 /*
   2  * Copyright (c) 2003, 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 <stdarg.h>
  26 #include <stdlib.h>
  27 #include <string.h>
  28 
  29 #include <jvmti.h>
  30 #include "agent_common.h"
  31 
  32 #include "nsk_tools.h"
  33 #include "JVMTITools.h"
  34 #include "jvmti_tools.h"
  35 
  36 extern "C" {
  37 
  38 #define PASSED  0
  39 #define STATUS_FAILED  2
  40 
  41 /* classes which must have the class load event */
  42 static const char *expSigs[] = {
  43     "Lnsk/jvmti/ClassLoad/classload001;",
  44     "Lnsk/jvmti/ClassLoad/classload001$TestedClass;"
  45 };
  46 #define EXP_SIG_NUM (sizeof(expSigs)/sizeof(char*))
  47 
  48 /* classes which must not have the class load event */
  49 static const char *unexpSigs[] = {
  50     "Z", /* boolean */
  51     "B", /* byte */
  52     "C", /* char */
  53     "D", /* double */
  54     "F", /* float */
  55     "I", /* integer */
  56     "J", /* long */
  57     "S", /* short */
  58 
  59     "[Z", /* boolean array */
  60     "[B", /* byte array */
  61     "[C", /* char array */
  62     "[D", /* double array */
  63     "[F", /* float array */
  64     "[I", /* integer array */
  65     "[J", /* long array */
  66     "[S", /* short array */
  67     "[Lnsk/jvmti/ClassLoad/classload001$TestedClass;"
  68 };
  69 #define UNEXP_SIG_NUM (sizeof(unexpSigs)/sizeof(char*))
  70 
  71 static volatile int clsEvents[EXP_SIG_NUM];
  72 static volatile int primClsEvents[UNEXP_SIG_NUM];
  73 
  74 static jint result = PASSED;
  75 static jvmtiEnv *jvmti = NULL;
  76 static jvmtiEventCallbacks callbacks;
  77 static jrawMonitorID countLock;
  78 
  79 static void initCounters() {
  80     size_t i;
  81 
  82     for(i=0; i<EXP_SIG_NUM; i++)
  83         clsEvents[i] = 0;
  84 
  85     for(i=0; i<UNEXP_SIG_NUM; i++)
  86         primClsEvents[i] = 0;
  87 }
  88 
  89 static int findSig(char *sig, int expected) {
  90     unsigned int i;
  91 
  92     for (i=0; i<((expected==1)?EXP_SIG_NUM:UNEXP_SIG_NUM); i++)
  93         if (sig != NULL &&
  94                 strcmp(((expected==1)?expSigs[i]:unexpSigs[i]), sig) == 0)
  95             return i; /* the signature found, return index */
  96 
  97     return -1; /* the signature not found */
  98 }
  99 
 100 static void lock(jvmtiEnv *jvmti_env, JNIEnv *jni_env) {
 101     if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorEnter(countLock)))
 102         jni_env->FatalError("failed to enter a raw monitor\n");
 103 }
 104 
 105 static void unlock(jvmtiEnv *jvmti_env, JNIEnv *jni_env) {
 106     if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorExit(countLock)))
 107         jni_env->FatalError("failed to exit a raw monitor\n");
 108 }
 109 
 110 /** callback functions **/
 111 void JNICALL
 112 ClassLoad(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread, jclass klass) {
 113     int i = 0;
 114     char *sig, *generic;
 115 
 116     lock(jvmti_env, env);
 117 
 118     if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &sig, &generic))) {
 119         result = STATUS_FAILED;
 120         NSK_COMPLAIN0("TEST FAILURE: unable to obtain a class signature\n");
 121     }
 122 
 123     if ((i = findSig(sig, 1)) != -1) {
 124         clsEvents[i]++;
 125         NSK_DISPLAY1("CHECK PASSED: ClassLoad event received for the class \"%s\" as expected\n",
 126             sig);
 127     }
 128     else if ((i = findSig(sig, 0)) != -1) {
 129         result = STATUS_FAILED;
 130         primClsEvents[i]++;
 131         NSK_COMPLAIN1(
 132             "TEST FAILED: JVMTI_EVENT_CLASS_LOAD event received for\n"
 133             "\t a primitive class/array of primitive types with the signature \"%s\"\n",
 134             sig);
 135     }
 136 
 137     unlock(jvmti_env, env);
 138 }
 139 /************************/
 140 
 141 JNIEXPORT jint JNICALL
 142 Java_nsk_jvmti_ClassLoad_classload001_check(
 143         JNIEnv *env, jobject obj) {
 144     size_t i;
 145 
 146     for (i=0; i<EXP_SIG_NUM; i++)
 147         if (clsEvents[i] != 1) {
 148             result = STATUS_FAILED;
 149             NSK_COMPLAIN2("TEST FAILED: wrong number of JVMTI_EVENT_CLASS_LOAD events for \"%s\":\n\tgot: %d\texpected: 1\n",
 150                 expSigs[i], clsEvents[i]);
 151         }
 152 
 153     for (i=0; i<UNEXP_SIG_NUM; i++)
 154         if (primClsEvents[i] != 0)
 155             NSK_COMPLAIN0("TEST FAILED: there are JVMTI_EVENT_CLASS_LOAD events for the primitive classes\n");
 156 
 157     return result;
 158 }
 159 
 160 #ifdef STATIC_BUILD
 161 JNIEXPORT jint JNICALL Agent_OnLoad_classload001(JavaVM *jvm, char *options, void *reserved) {
 162     return Agent_Initialize(jvm, options, reserved);
 163 }
 164 JNIEXPORT jint JNICALL Agent_OnAttach_classload001(JavaVM *jvm, char *options, void *reserved) {
 165     return Agent_Initialize(jvm, options, reserved);
 166 }
 167 JNIEXPORT jint JNI_OnLoad_classload001(JavaVM *jvm, char *options, void *reserved) {
 168     return JNI_VERSION_1_8;
 169 }
 170 #endif
 171 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 172     /* init framework and parse options */
 173     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 174         return JNI_ERR;
 175 
 176     /* create JVMTI environment */
 177     if (!NSK_VERIFY((jvmti =
 178             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
 179         return JNI_ERR;
 180 
 181     initCounters();
 182 
 183     if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_counter_lock", &countLock)))
 184         return JNI_ERR;
 185 
 186     NSK_DISPLAY0("setting event callbacks ...\n");
 187     (void) memset(&callbacks, 0, sizeof(callbacks));
 188     callbacks.ClassLoad = &ClassLoad;
 189     if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks))))
 190         return JNI_ERR;
 191 
 192     NSK_DISPLAY0("setting event callbacks done\nenabling ClassLoad event ...\n");
 193     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL)))
 194         return JNI_ERR;
 195     NSK_DISPLAY0("the event enabled\n");
 196 
 197     return JNI_OK;
 198 }
 199 
 200 }