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 27 #include <jvmti.h> 28 #include "agent_common.h" 29 30 #include "nsk_tools.h" 31 #include "native_thread.h" 32 #include "JVMTITools.h" 33 #include "jvmti_tools.h" 34 35 extern "C" { 36 37 #define PASSED 0 38 #define STATUS_FAILED 2 39 40 #define MAX_ATTEMPTS 15 41 42 static const char *expHSMethod = "entryMethod2"; 43 static const char *expHSSignature = "()V"; 44 45 #define EVENTS_COUNT 4 46 static jvmtiEvent eventsList[EVENTS_COUNT] = { 47 JVMTI_EVENT_EXCEPTION, 48 JVMTI_EVENT_METHOD_ENTRY, 49 JVMTI_EVENT_METHOD_EXIT, 50 JVMTI_EVENT_FRAME_POP 51 }; 52 53 static jvmtiEnv *jvmti = NULL; 54 static jlong timeout = 0; 55 56 static jint bytesCount; /* number of bytes of a redefining class */ 57 static jbyte *clsBytes; /* bytes defining a redefining class */ 58 59 static jint redefMethBytesCount; /* number of bytes of a redefined method */ 60 static unsigned char *redefMethBytes; /* bytes defining a redefined method */ 61 62 JNIEXPORT void JNICALL Java_nsk_jvmti_scenarios_hotswap_HS201_hs201t003_storeClassBytes 63 (JNIEnv *jni_env, jclass cls, jbyteArray classBytes) { 64 jboolean isCopy; 65 66 bytesCount = NSK_CPP_STUB2(GetArrayLength, jni_env, classBytes); 67 clsBytes = 68 NSK_CPP_STUB3(GetByteArrayElements, jni_env, classBytes, &isCopy); 69 } 70 71 static int expectedMeth(jvmtiEnv *jvmti_env, const char *event, 72 jmethodID method, const char *expMeth, const char *expSig) { 73 char *name; 74 char *sig; 75 int methFound = 0; 76 77 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB5(GetMethodName, 78 jvmti_env, method, &name, &sig, NULL))) { 79 nsk_jvmti_setFailStatus(); 80 return 0; 81 } 82 83 if ((strcmp(name, expMeth) == 0) && (strcmp(sig, expSig) == 0)) { 84 NSK_DISPLAY4( 85 "===== %s event received for the tested method:\n" 86 "\tID=0x%p name=\"%s\" signature=\"%s\"\n", 87 event, (void*) method, name, sig); 88 methFound = 1; 89 } 90 else 91 methFound = 0; 92 93 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, 94 jvmti_env, (unsigned char*) name))) 95 nsk_jvmti_setFailStatus(); 96 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, 97 jvmti_env, (unsigned char*) sig))) 98 nsk_jvmti_setFailStatus(); 99 100 return methFound; 101 } 102 103 static void doHotSwap(jvmtiEnv *jvmti_env, 104 jmethodID tMethodID, const char *event) { 105 jclass decl_cls; 106 char *cls_sig; 107 jvmtiClassDefinition classDef; 108 109 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetMethodDeclaringClass, 110 jvmti_env, tMethodID, &decl_cls))) { 111 nsk_jvmti_setFailStatus(); 112 return; 113 } 114 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, 115 jvmti_env, decl_cls, &cls_sig, NULL))) { 116 nsk_jvmti_setFailStatus(); 117 return; 118 } 119 else 120 NSK_DISPLAY2("[%s] tested method class signature: \"%s\"\n\n", 121 event, cls_sig); 122 123 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, 124 jvmti_env, (unsigned char*) cls_sig))) 125 nsk_jvmti_setFailStatus(); 126 127 /* fill the structure jvmtiClassDefinition */ 128 classDef.klass = decl_cls; 129 classDef.class_byte_count = bytesCount; 130 classDef.class_bytes = (unsigned char*) clsBytes; 131 132 NSK_DISPLAY2( 133 "[%s] >>>>> Invoke RedefineClasses():\n" 134 "\tnew class byte count=%d\n", 135 event, classDef.class_byte_count); 136 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(RedefineClasses, 137 jvmti, 1, &classDef))) { 138 nsk_jvmti_setFailStatus(); 139 return; 140 } 141 NSK_DISPLAY1("[%s] <<<<< RedefineClasses() is successfully done\n", 142 event); 143 } 144 145 static void doChecks(jvmtiEnv *jvmti_env, 146 jmethodID tMethodID, jboolean expected, const char *event) { 147 jboolean isObsolete = JNI_FALSE; 148 char *name; 149 char *sig; 150 jint methBytesCount; /* number of bytes of a method */ 151 unsigned char *methBytes; /* bytes defining a method */ 152 153 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB5(GetMethodName, 154 jvmti_env, tMethodID, &name, &sig, NULL))) { 155 nsk_jvmti_setFailStatus(); 156 return; 157 } 158 NSK_DISPLAY4("[%s] method ID=0x%p name=\"%s\" signature=\"%s\"\n", 159 event, (void*) tMethodID, name, sig); 160 161 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetBytecodes, 162 jvmti_env, tMethodID, &methBytesCount, &methBytes))) { 163 nsk_jvmti_setFailStatus(); 164 return; 165 } 166 NSK_DISPLAY3( 167 "[%s] method bytes count=%d\n" 168 "\tbytes count of the redefined method=%d\n", 169 event, methBytesCount, redefMethBytesCount); 170 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, 171 jvmti_env, (unsigned char*) methBytes))) 172 nsk_jvmti_setFailStatus(); 173 174 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(IsMethodObsolete, 175 jvmti_env, tMethodID, &isObsolete))) { 176 nsk_jvmti_setFailStatus(); 177 return; 178 } 179 if ((methBytesCount == redefMethBytesCount && isObsolete == JNI_TRUE) || 180 (methBytesCount != redefMethBytesCount && isObsolete == JNI_FALSE)) { 181 NSK_DISPLAY3("[%s] CHECK PASSED: IsMethodObsolete = %d(%s) as expected\n", 182 event, (int)isObsolete, 183 (isObsolete==JNI_TRUE)?"TRUE":"FALSE"); 184 } 185 else { 186 nsk_jvmti_setFailStatus(); 187 NSK_COMPLAIN4("[%s] TEST FAILED: IsMethodObsolete = %d(%s), expected: %s\n", 188 event, (int)isObsolete, 189 (isObsolete == JNI_TRUE)?"TRUE":"FALSE", 190 (methBytesCount == redefMethBytesCount)?"TRUE":"FALSE"); 191 } 192 } 193 194 /** callback functions **/ 195 void JNICALL MethodEntry(jvmtiEnv *jvmti_env, JNIEnv *env, 196 jthread thr, jmethodID method) { 197 198 if (expectedMeth(jvmti_env, "MethodEntry", 199 method, expHSMethod, expHSSignature)==1) { 200 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetBytecodes, 201 jvmti_env, method, &redefMethBytesCount, &redefMethBytes))) 202 nsk_jvmti_setFailStatus(); 203 else { 204 NSK_DISPLAY2("[MethodEntry] thread=0x%p method bytes count=%d\n", 205 thr, redefMethBytesCount); 206 207 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(NotifyFramePop, 208 jvmti_env, thr, 0))) 209 nsk_jvmti_setFailStatus(); 210 } 211 212 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, 213 jvmti_env, JVMTI_DISABLE, JVMTI_EVENT_METHOD_ENTRY, NULL))) 214 nsk_jvmti_setFailStatus(); 215 } 216 } 217 218 void JNICALL 219 Exception(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr, 220 jmethodID method, jlocation location, jobject exception, 221 jmethodID catch_method, jlocation catch_location) { 222 223 if (expectedMeth(jvmti_env, "Exception", 224 method, expHSMethod, expHSSignature)==1) { 225 NSK_DISPLAY1("[Exception] thread=0x%p\n", thr); 226 227 doHotSwap(jvmti_env, method, "Exception"); 228 doChecks(jvmti_env, method, JNI_TRUE, "Exception"); 229 } 230 } 231 232 void JNICALL 233 MethodExit(jvmtiEnv *jvmti_env, JNIEnv *env, 234 jthread thr, jmethodID method, 235 jboolean was_poped_by_exc, jvalue return_value) { 236 237 if (expectedMeth(jvmti_env, "MethodExit", 238 method, expHSMethod, expHSSignature)==1) { 239 NSK_DISPLAY1("[MethodExit] thread=0x%p\n", thr); 240 241 doHotSwap(jvmti_env, method, "MethodExit"); 242 doChecks(jvmti_env, method, JNI_TRUE, "MethodExit"); 243 } 244 } 245 246 void JNICALL 247 FramePop(jvmtiEnv *jvmti_env, JNIEnv *env, 248 jthread thr, jmethodID method, jboolean wasPopedByException) { 249 if (expectedMeth(jvmti_env, "FramePop", 250 method, expHSMethod, expHSSignature)==1) { 251 NSK_DISPLAY1("[FramePop] thread=0x%p\n", thr); 252 253 doHotSwap(jvmti_env, method, "FramePop"); 254 doChecks(jvmti_env, method, JNI_TRUE, "FramePop"); 255 } 256 } 257 /************************/ 258 259 /** agent's procedure **/ 260 static void JNICALL 261 agentProc(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg) { 262 int tries = 0; 263 264 /* testing sync */ 265 NSK_DISPLAY1("agentProc: waiting for the debuggee start for %d msecs...\n\n", 266 (int) timeout); 267 if (!nsk_jvmti_waitForSync(timeout)) 268 return; 269 NSK_DISPLAY0("agentProc: resuming the debuggee ...\n\n"); 270 if (!nsk_jvmti_resumeSync()) 271 return; 272 273 /* testing sync */ 274 NSK_DISPLAY1("agentProc: waiting for the debuggee finish for %d msecs...\n\n", 275 (int) timeout); 276 if (!nsk_jvmti_waitForSync(timeout)) 277 return; 278 279 /* deallocating used memory */ 280 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, 281 jvmti_env, (unsigned char*) redefMethBytes))) 282 nsk_jvmti_setFailStatus(); 283 284 NSK_DISPLAY0("agentProc: final resuming of the debuggee ...\n\n"); 285 if (!nsk_jvmti_resumeSync()) 286 return; 287 288 NSK_DISPLAY0("agentProc: finished\n\n"); 289 } 290 291 #ifdef STATIC_BUILD 292 JNIEXPORT jint JNICALL Agent_OnLoad_hs201t003(JavaVM *jvm, char *options, void *reserved) { 293 return Agent_Initialize(jvm, options, reserved); 294 } 295 JNIEXPORT jint JNICALL Agent_OnAttach_hs201t003(JavaVM *jvm, char *options, void *reserved) { 296 return Agent_Initialize(jvm, options, reserved); 297 } 298 JNIEXPORT jint JNI_OnLoad_hs201t003(JavaVM *jvm, char *options, void *reserved) { 299 return JNI_VERSION_1_8; 300 } 301 #endif 302 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 303 jvmtiCapabilities caps; 304 jvmtiEventCallbacks callbacks; 305 306 /* init framework and parse options */ 307 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 308 return JNI_ERR; 309 310 /* obtain WAITTIME parameter */ 311 timeout = nsk_jvmti_getWaitTime() * 60000; 312 NSK_DISPLAY1("waittime=%d msecs\n", (int) timeout); 313 314 /* create JVMTI environment */ 315 if (!NSK_VERIFY((jvmti = 316 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 317 return JNI_ERR; 318 319 /* add required capabilities */ 320 memset(&caps, 0, sizeof(jvmtiCapabilities)); 321 caps.can_get_bytecodes = 1; 322 caps.can_generate_exception_events = 1; 323 caps.can_generate_method_entry_events = 1; 324 caps.can_generate_method_exit_events = 1; 325 caps.can_generate_frame_pop_events = 1; 326 caps.can_redefine_classes = 1; 327 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, 328 jvmti, &caps))) 329 return JNI_ERR; 330 331 /* set event callback */ 332 NSK_DISPLAY0("setting event callbacks ...\n"); 333 (void) memset(&callbacks, 0, sizeof(callbacks)); 334 callbacks.Exception = &Exception; 335 callbacks.MethodEntry = &MethodEntry; 336 callbacks.MethodExit = &MethodExit; 337 callbacks.FramePop = &FramePop; 338 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetEventCallbacks, 339 jvmti, &callbacks, sizeof(callbacks)))) 340 return JNI_ERR; 341 342 NSK_DISPLAY0("setting event callbacks done\nenabling events ...\n"); 343 if (!nsk_jvmti_enableEvents(JVMTI_ENABLE, EVENTS_COUNT, 344 eventsList, NULL)) 345 return JNI_ERR; 346 347 NSK_DISPLAY0("enabling the events done\n\n"); 348 349 /* register agent proc */ 350 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 351 return JNI_ERR; 352 353 return JNI_OK; 354 } 355 356 }