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