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 25 Unit test to test the following: 26 27 Onload phase: 28 29 1. CreateRawMonitor 30 2. RawMonitorEnter 31 3. RawMonitorExit 32 4. DestroyRawMonitor 33 5. Recursive RawMonitorEnter and DestroyRawMonitor 34 6. RawMonitorExit for not owned monitor in onload phase. 35 7. RawMonitorExit for not owned monitor in live phase. 36 37 Mixed phase: 38 39 1. Onload RawMonitorEnter and live phase RawMonitorExit 40 2. Onload RawMonitorEnter and start phase RawMonitorExit 41 3. Start phase RawMonitorEnter and RawMonitorExit. 42 4. Onload RawmonitorEnter and start phase Destroy 43 44 */ 45 46 #include <stdio.h> 47 #include <string.h> 48 #include "jvmti.h" 49 #include "agent_common.h" 50 51 extern "C" { 52 53 54 #define JVMTI_ERROR_CHECK(str,res) if ( res != JVMTI_ERROR_NONE) { printf(str); printf(" %d\n",res); return res;} 55 #define JVMTI_ERROR_CHECK_EXPECTED_ERROR(str,res,err) if ( res != err) { printf(str); printf(" unexpected error %d\n",res); return res;} 56 57 #define JVMTI_ERROR_CHECK_VOID(str,res) if ( res != JVMTI_ERROR_NONE) { printf(str); printf(" %d\n",res); iGlobalStatus = 2; } 58 59 #define JVMTI_ERROR_CHECK_EXPECTED_ERROR_VOID(str,res,err) if ( res != err) { printf(str); printf(" unexpected error %d\n",res); iGlobalStatus = 2; } 60 61 #define THREADS_LIMIT 8 62 63 jrawMonitorID access_lock; 64 jrawMonitorID access_lock_not_entered; 65 jvmtiEnv *jvmti; 66 jint iGlobalStatus = 0; 67 jthread main_thread; 68 static jvmtiEventCallbacks callbacks; 69 static jvmtiCapabilities jvmti_caps; 70 jrawMonitorID jraw_monitor[20]; 71 72 static volatile int process_once = 1; 73 74 75 76 int printdump = 0; 77 78 79 void debug_printf(const char *fmt, ...) { 80 va_list args; 81 82 va_start(args, fmt); 83 if (printdump) { 84 vprintf(fmt, args); 85 } 86 va_end(args); 87 } 88 89 90 void JNICALL vmStart(jvmtiEnv *jvmti_env, JNIEnv *env) { 91 jvmtiError res; 92 res = jvmti->GetCurrentThread(&main_thread); 93 JVMTI_ERROR_CHECK_VOID(" JVMTI GetCurrentThread returned error", res); 94 main_thread = (jthread)env->NewGlobalRef(main_thread); 95 } 96 97 void JNICALL vmInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) { 98 99 jvmtiError res; 100 101 debug_printf("VMInit event done\n"); 102 res = jvmti->RawMonitorExit(access_lock); 103 JVMTI_ERROR_CHECK_VOID(" Raw monitor exit returned error", res); 104 res = jvmti->RawMonitorExit(access_lock); 105 JVMTI_ERROR_CHECK_VOID(" Raw monitor exit returned error", res); 106 } 107 108 void JNICALL vmExit(jvmtiEnv *jvmti_env, JNIEnv *env) { 109 debug_printf("------------ JVMTI_EVENT_VM_DEATH ------------\n"); 110 } 111 112 void JNICALL classFileLoadHookEvent(jvmtiEnv *jvmti_env, JNIEnv *env, 113 jclass class_being_redifined, 114 jobject loader, const char* name, 115 jobject protection_domain, 116 jint class_data_len, 117 const unsigned char* class_data, 118 jint* new_class_data_len, 119 unsigned char** new_class_data) { 120 121 jvmtiError res; 122 jvmtiPhase phase; 123 jthread thread; 124 125 res = jvmti->GetPhase(&phase); 126 JVMTI_ERROR_CHECK_VOID(" JVMTI GetPhase returned error", res); 127 if (phase != JVMTI_PHASE_START) { 128 return; /* only the start phase is tested */ 129 } 130 res = jvmti->GetCurrentThread(&thread); 131 JVMTI_ERROR_CHECK_VOID(" JVMTI GetCurrentThread returned error", res); 132 if (!env->IsSameObject(thread, main_thread)) { 133 return; /* only the main thread is tested */ 134 } 135 136 debug_printf("------------ classFileLoadHookEvent ------------\n"); 137 138 /* Test raw monitor in start phase */ 139 140 if (process_once) { 141 142 process_once = 0; 143 144 /* test not entered raw monitor */ 145 res = jvmti->RawMonitorExit(access_lock_not_entered); 146 JVMTI_ERROR_CHECK_EXPECTED_ERROR_VOID("Raw monitor exit returned error", res,JVMTI_ERROR_NOT_MONITOR_OWNER); 147 148 /* release lock in start phase */ 149 res = jvmti->RawMonitorExit(access_lock); 150 JVMTI_ERROR_CHECK_VOID("Raw monitor exit returned error", res); 151 152 /* release lock in start phase */ 153 res = jvmti->RawMonitorExit(access_lock); 154 JVMTI_ERROR_CHECK_VOID("Raw monitor exit returned error", res); 155 156 res = jvmti->RawMonitorEnter(access_lock); 157 JVMTI_ERROR_CHECK_VOID("Raw monitor enter returned error", res); 158 159 res = jvmti->RawMonitorEnter(access_lock); 160 JVMTI_ERROR_CHECK_VOID("Raw monitor enter returned error", res); 161 } 162 163 } 164 165 166 167 void init_callbacks() { 168 memset((void *)&callbacks, 0, sizeof(jvmtiEventCallbacks)); 169 callbacks.VMStart = vmStart; 170 callbacks.VMInit = vmInit; 171 callbacks.VMDeath = vmExit; 172 callbacks.ClassFileLoadHook = classFileLoadHookEvent; 173 } 174 175 176 #ifdef STATIC_BUILD 177 JNIEXPORT jint JNICALL Agent_OnLoad_rawmonitor(JavaVM *jvm, char *options, void *reserved) { 178 return Agent_Initialize(jvm, options, reserved); 179 } 180 JNIEXPORT jint JNICALL Agent_OnAttach_rawmonitor(JavaVM *jvm, char *options, void *reserved) { 181 return Agent_Initialize(jvm, options, reserved); 182 } 183 JNIEXPORT jint JNI_OnLoad_rawmonitor(JavaVM *jvm, char *options, void *reserved) { 184 return JNI_VERSION_1_8; 185 } 186 #endif 187 jint Agent_Initialize(JavaVM * jvm, char *options, void *reserved) { 188 jint res; 189 190 if (options && strlen(options) > 0) { 191 if (strstr(options, "printdump")) { 192 printdump = 1; 193 } 194 } 195 196 res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1); 197 if (res < 0) { 198 debug_printf("Wrong result of a valid call to GetEnv!\n"); 199 return JNI_ERR; 200 } 201 202 /* Onload phase Create data access lock */ 203 res = jvmti->CreateRawMonitor("_access_lock", &access_lock); 204 JVMTI_ERROR_CHECK("CreateRawMonitor failed with error code ", res); 205 res = jvmti->CreateRawMonitor("_access_lock_not_entered", &access_lock_not_entered); 206 JVMTI_ERROR_CHECK("CreateRawMonitor failed with error code ", res); 207 /* Create this raw monitor in onload and it is used in live phase */ 208 res = jvmti->CreateRawMonitor("RawMonitor-0", &jraw_monitor[0]); 209 JVMTI_ERROR_CHECK("CreateRawMonitor failed with error code ", res); 210 211 212 /* Add capabilities */ 213 res = jvmti->GetPotentialCapabilities(&jvmti_caps); 214 JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res); 215 216 res = jvmti->AddCapabilities(&jvmti_caps); 217 JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res); 218 219 /* Enable events */ 220 init_callbacks(); 221 res = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)); 222 JVMTI_ERROR_CHECK("SetEventCallbacks returned error", res); 223 224 res = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); 225 JVMTI_ERROR_CHECK("SetEventNotificationMode for VM_INIT returned error", res); 226 227 res = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL); 228 JVMTI_ERROR_CHECK("SetEventNotificationMode for vm death event returned error", res); 229 230 res = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL); 231 JVMTI_ERROR_CHECK("SetEventNotificationMode CLASS_FILE_LOAD_HOOK returned error", res); 232 233 /* acquire lock in onload */ 234 res = jvmti->RawMonitorEnter(access_lock); 235 JVMTI_ERROR_CHECK("Raw monitor enter returned error", res); 236 237 /* release lock in onload */ 238 res = jvmti->RawMonitorExit(access_lock); 239 JVMTI_ERROR_CHECK("Raw monitor exit returned error", res); 240 241 /* test not entered raw monitor */ 242 res = jvmti->RawMonitorExit(access_lock_not_entered); 243 JVMTI_ERROR_CHECK_EXPECTED_ERROR("Raw monitor exit returned error", res,JVMTI_ERROR_NOT_MONITOR_OWNER); 244 245 /* acquire lock in onload */ 246 res = jvmti->RawMonitorEnter(access_lock); 247 JVMTI_ERROR_CHECK("Raw monitor enter returned error", res); 248 249 res = jvmti->RawMonitorEnter(access_lock); 250 JVMTI_ERROR_CHECK("Raw monitor enter returned error", res); 251 252 res = jvmti->RawMonitorEnter(access_lock); 253 JVMTI_ERROR_CHECK("Raw monitor enter returned error", res); 254 255 /* test Destroy raw monitor in onload phase */ 256 res = jvmti->DestroyRawMonitor(access_lock); 257 JVMTI_ERROR_CHECK("Destroy Raw monitor returned error", res); 258 259 /* Create data access lock in onload and enter in onload phase */ 260 res = jvmti->CreateRawMonitor("_access_lock", &access_lock); 261 JVMTI_ERROR_CHECK("CreateRawMonitor failed with error code ", res); 262 263 res = jvmti->RawMonitorEnter(access_lock); 264 JVMTI_ERROR_CHECK("Raw monitor enter returned error", res); 265 266 res = jvmti->RawMonitorEnter(access_lock); 267 JVMTI_ERROR_CHECK("Raw monitor enter returned error", res); 268 269 270 /* This monitor is entered here and it is released in live phase by a call from java code 271 */ 272 res = jvmti->RawMonitorEnter(jraw_monitor[0]); 273 JVMTI_ERROR_CHECK("Raw monitor enter returned error", res); 274 res = jvmti->RawMonitorEnter(jraw_monitor[0]); 275 JVMTI_ERROR_CHECK("Raw monitor enter returned error", res); 276 res = jvmti->RawMonitorExit(jraw_monitor[0]); 277 JVMTI_ERROR_CHECK("Raw monitor exit returned error", res); 278 279 return JNI_OK; 280 } 281 282 283 JNIEXPORT jint JNICALL 284 Java_nsk_jvmti_unit_functions_rawmonitor_GetResult(JNIEnv * env, jclass cls) { 285 return iGlobalStatus; 286 } 287 288 289 JNIEXPORT void JNICALL 290 Java_nsk_jvmti_unit_functions_rawmonitor_CreateRawMonitor(JNIEnv * env, jclass klass, jint i) { 291 jvmtiError ret; 292 char sz[128]; 293 294 sprintf(sz, "Rawmonitor-%d",i); 295 debug_printf("jvmti create raw monitor \n"); 296 ret = jvmti->CreateRawMonitor(sz, &jraw_monitor[i]); 297 298 if (ret != JVMTI_ERROR_NONE) { 299 printf("Error: CreateRawMonitor %d \n", ret); 300 iGlobalStatus = 2; 301 } 302 } 303 304 JNIEXPORT void JNICALL 305 Java_nsk_jvmti_unit_functions_rawmonitor_RawMonitorEnter(JNIEnv * env, jclass cls, jint i) { 306 jvmtiError ret; 307 308 debug_printf("jvmti Raw monitor enter \n"); 309 ret = jvmti->RawMonitorEnter(jraw_monitor[i]); 310 311 if (ret != JVMTI_ERROR_NONE) { 312 printf("Error: RawMonitorEnter %d \n", ret); 313 iGlobalStatus = 2; 314 } 315 } 316 317 JNIEXPORT void JNICALL 318 Java_nsk_jvmti_unit_functions_rawmonitor_RawMonitorExit(JNIEnv * env, jclass cls, jint i) { 319 jvmtiError ret; 320 321 debug_printf("jvmti raw monitor exit \n"); 322 ret = jvmti->RawMonitorExit(jraw_monitor[i]); 323 324 if (ret != JVMTI_ERROR_NONE) { 325 printf("Error: RawMonitorExit %d \n", ret); 326 iGlobalStatus = 2; 327 } 328 } 329 330 JNIEXPORT void JNICALL 331 Java_nsk_jvmti_unit_functions_rawmonitor_RawMonitorWait(JNIEnv * env, jclass cls, jint i) { 332 jvmtiError ret; 333 334 debug_printf("jvmti RawMonitorWait \n"); 335 ret = jvmti->RawMonitorWait(jraw_monitor[i], -1); 336 337 if (ret != JVMTI_ERROR_NONE) { 338 printf("Error: RawMonitorWait %d \n", ret); 339 iGlobalStatus = 2; 340 } 341 } 342 343 }