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 <stdlib.h> 25 #include <string.h> 26 #include "jvmti.h" 27 #include "agent_common.h" 28 #include "jni_tools.h" 29 #include "jvmti_tools.h" 30 31 extern "C" { 32 33 #define PASSED 0 34 #define STATUS_FAILED 2 35 36 /* ============================================================================= */ 37 38 static jlong timeout = 0; 39 static const char* segment = NULL; 40 static const char* EXP_CLASS_SIGNATURE = "Lnsk/jvmti/scenarios/general_functions/GF04/gf04t001;"; 41 static jrawMonitorID countLock; 42 static jboolean classLoadReceived = JNI_FALSE, classPrepareReceived = JNI_FALSE; 43 static jint result = PASSED; 44 45 /* ============================================================================= */ 46 47 /** 48 * Add segment to bootstrap classloader path. 49 * @returns NSK_FALSE if any error occured. 50 */ 51 static int addSegment(jvmtiEnv* jvmti, const char segment[], const char where[]) { 52 void* storage = NULL; 53 54 NSK_DISPLAY1("Add segment: %s\n", segment); 55 if (!NSK_JVMTI_VERIFY( 56 NSK_CPP_STUB2(AddToBootstrapClassLoaderSearch, jvmti, segment))) { 57 return NSK_FALSE; 58 } 59 NSK_DISPLAY0(" ... added\n"); 60 61 return NSK_TRUE; 62 } 63 64 static void setupLock(jvmtiEnv *jvmti_env, JNIEnv *jni_env) { 65 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, 66 jvmti_env, countLock))) 67 NSK_CPP_STUB2(FatalError, jni_env, 68 "failed to enter a raw monitor\n"); 69 } 70 71 static void setoffLock(jvmtiEnv *jvmti_env, JNIEnv *jni_env) { 72 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, 73 jvmti_env, countLock))) 74 NSK_CPP_STUB2(FatalError, jni_env, 75 "failed to exit a raw monitor\n"); 76 } 77 78 JNIEXPORT jint JNICALL 79 Java_nsk_jvmti_scenarios_general_1functions_GF04_gf04t001_check( 80 JNIEnv *env, jobject obj) { 81 if (result == PASSED && classLoadReceived == JNI_TRUE && classPrepareReceived == JNI_TRUE) { 82 return PASSED; 83 } 84 return STATUS_FAILED; 85 } 86 87 /* ============================================================================= */ 88 89 /** callback for ClassLoad event **/ 90 void JNICALL 91 ClassLoad(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread, jclass klass) { 92 char *sig, *generic; 93 94 setupLock(jvmti_env, env); 95 96 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, 97 jvmti_env, klass, &sig, &generic))) { 98 result = STATUS_FAILED; 99 } 100 101 if (strcmp(sig, EXP_CLASS_SIGNATURE) == 0) { 102 NSK_DISPLAY1("CHECK PASSED: ClassLoad event received for the class \"%s\" as expected\n", 103 sig); 104 classLoadReceived = JNI_TRUE; 105 106 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 107 jvmti_env, JVMTI_DISABLE, JVMTI_EVENT_CLASS_LOAD, NULL))) { 108 result = STATUS_FAILED; 109 } else { 110 NSK_DISPLAY0("ClassLoad event disabled\n"); 111 } 112 } 113 114 setoffLock(jvmti_env, env); 115 } 116 117 /** callback for ClassPrepare event **/ 118 void JNICALL 119 ClassPrepare(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread, jclass klass) { 120 char *sig, *generic; 121 122 setupLock(jvmti_env, env); 123 124 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, 125 jvmti_env, klass, &sig, &generic))) { 126 result = STATUS_FAILED; 127 } 128 129 if (strcmp(sig, EXP_CLASS_SIGNATURE) == 0) { 130 NSK_DISPLAY1("CHECK PASSED: ClassPrepare event received for the class \"%s\" as expected\n", 131 sig); 132 classPrepareReceived = JNI_TRUE; 133 134 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 135 jvmti_env, JVMTI_DISABLE, JVMTI_EVENT_CLASS_PREPARE, NULL))) { 136 result = STATUS_FAILED; 137 } else { 138 NSK_DISPLAY0("ClassPrepare event disabled\n"); 139 } 140 } 141 142 setoffLock(jvmti_env, env); 143 } 144 145 /* ============================================================================= */ 146 147 /** Agent library initialization. */ 148 #ifdef STATIC_BUILD 149 JNIEXPORT jint JNICALL Agent_OnLoad_gf04t001(JavaVM *jvm, char *options, void *reserved) { 150 return Agent_Initialize(jvm, options, reserved); 151 } 152 JNIEXPORT jint JNICALL Agent_OnAttach_gf04t001(JavaVM *jvm, char *options, void *reserved) { 153 return Agent_Initialize(jvm, options, reserved); 154 } 155 JNIEXPORT jint JNI_OnLoad_gf04t001(JavaVM *jvm, char *options, void *reserved) { 156 return JNI_VERSION_1_8; 157 } 158 #endif 159 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 160 jvmtiEnv* jvmti = NULL; 161 162 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 163 return JNI_ERR; 164 165 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 166 167 segment = nsk_jvmti_findOptionStringValue("segment", NULL); 168 if (!NSK_VERIFY(segment != NULL)) 169 return JNI_ERR; 170 171 if (!NSK_VERIFY((jvmti = 172 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 173 return JNI_ERR; 174 175 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(CreateRawMonitor, 176 jvmti, "eventLock", &countLock))) 177 return JNI_ERR; 178 179 NSK_DISPLAY0("Add bootstrap class load segment in Agent_OnLoad()\n"); 180 if (!addSegment(jvmti, segment, "Agent_OnLoad()")) { 181 return JNI_ERR; 182 } 183 184 NSK_DISPLAY0("Setting callbacks for events:\n"); 185 { 186 jvmtiEventCallbacks callbacks; 187 jint size = (jint)sizeof(callbacks); 188 189 memset(&callbacks, 0, sizeof(callbacks)); 190 callbacks.ClassLoad = &ClassLoad; 191 callbacks.ClassPrepare = &ClassPrepare; 192 if (!NSK_JVMTI_VERIFY( 193 NSK_CPP_STUB3(SetEventCallbacks, jvmti, &callbacks, size))) { 194 return JNI_ERR; 195 } 196 } 197 NSK_DISPLAY0(" ... set\n"); 198 199 NSK_DISPLAY0("Enabling events: \n"); 200 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 201 jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL))) { 202 return JNI_ERR; 203 } else { 204 NSK_DISPLAY0(" ... ClassLoad enabled\n"); 205 } 206 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 207 jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL))) { 208 return JNI_ERR; 209 } else { 210 NSK_DISPLAY0(" ... ClassPrepare enabled\n"); 211 } 212 213 return JNI_OK; 214 } 215 216 /* ============================================================================= */ 217 218 }