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