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 <string.h> 25 #include "jvmti.h" 26 #include "agent_common.h" 27 #include "jni_tools.h" 28 #include "jvmti_tools.h" 29 30 extern "C" { 31 32 /* scaffold objects */ 33 static jvmtiEnv *jvmti = NULL; 34 static jlong timeout = 0; 35 36 #define TESTED_CLASS_NAME "nsk/jvmti/scenarios/bcinstr/BI01/bi01t002a" 37 #define TOTAL_INSTRUMENTED_CLASSES 2 38 39 static int clsLoadedIdx=0; 40 static jint newClassSize[TOTAL_INSTRUMENTED_CLASSES]; 41 static unsigned char* newClassBytes[TOTAL_INSTRUMENTED_CLASSES]; 42 static jvmtiClassDefinition oldClassDef[TOTAL_INSTRUMENTED_CLASSES]; 43 44 /* ============================================================================= */ 45 /* 46 * Class: nsk_jvmti_scenarios_bcinstr_BI01_bi01t002 47 * Method: setNewByteCode 48 * Signature: (I[B)Z 49 */ 50 JNIEXPORT jboolean JNICALL 51 Java_nsk_jvmti_scenarios_bcinstr_BI01_bi01t002_setNewByteCode(JNIEnv *jni_env, 52 jobject o, jint ind, jbyteArray byteCode) { 53 54 jbyte* elements; 55 jboolean isCopy; 56 57 if (!NSK_JNI_VERIFY(jni_env, (newClassSize[ind] = jni_env->GetArrayLength(byteCode)) > 0)) { 58 nsk_jvmti_setFailStatus(); 59 return NSK_FALSE; 60 } 61 NSK_DISPLAY1("\t... got array size: %d\n", newClassSize[ind]); 62 63 if (!NSK_JNI_VERIFY(jni_env, (elements = 64 jni_env->GetByteArrayElements(byteCode, &isCopy)) != NULL)) { 65 nsk_jvmti_setFailStatus(); 66 return NSK_FALSE; 67 } 68 NSK_DISPLAY1("\t... got elements list: 0x%p\n", (void*)elements); 69 70 if (!NSK_JVMTI_VERIFY(jvmti->Allocate(newClassSize[ind], &newClassBytes[ind]))) { 71 nsk_jvmti_setFailStatus(); 72 return NSK_FALSE; 73 } 74 NSK_DISPLAY1("\t... created bytes array: 0x%p\n", (void*)newClassBytes[ind]); 75 76 { 77 int j; 78 for (j = 0; j < newClassSize[ind]; j++) 79 newClassBytes[ind][j] = (unsigned char)elements[j]; 80 } 81 NSK_DISPLAY1("\t... copied bytecode: %d bytes\n", (int)newClassSize[ind]); 82 83 NSK_DISPLAY1("\t... release elements list: 0x%p\n", (void*)elements); 84 NSK_TRACE(jni_env->ReleaseByteArrayElements(byteCode, elements, JNI_ABORT)); 85 NSK_DISPLAY0("\t... released\n"); 86 return NSK_TRUE; 87 } 88 89 /* ============================================================================= */ 90 /* 91 * Class: nsk_jvmti_scenarios_bcinstr_BI01_bi01t002 92 * Method: setClass 93 * Signature: (ILjava/lang/Class;)V 94 */ 95 JNIEXPORT void JNICALL 96 Java_nsk_jvmti_scenarios_bcinstr_BI01_bi01t002_setClass(JNIEnv *jni_env, 97 jobject o, jint ind, jclass cls) { 98 99 if (!NSK_JNI_VERIFY(jni_env, (oldClassDef[ind].klass = (jclass) 100 jni_env->NewGlobalRef(cls)) != NULL)) { 101 nsk_jvmti_setFailStatus(); 102 } 103 } 104 105 /* ============================================================================= */ 106 107 /** Callback function for ClassFileLoadHook event. */ 108 JNIEXPORT void JNICALL 109 cbClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv* jni_env, 110 jclass class_being_redefined, jobject loader, const char* name, 111 jobject protection_domain, jint class_data_len, 112 const unsigned char* class_data, jint* new_class_data_len, 113 unsigned char** new_class_data) { 114 115 if (name == NULL || strcmp(name, TESTED_CLASS_NAME)) { 116 return; 117 } 118 119 NSK_DISPLAY3("CLASS_FILE_LOAD_HOOK event: %s\n\treceived bytecode: 0x%p:%d\n", 120 name, (void *)class_data, class_data_len); 121 if (nsk_getVerboseMode()) { 122 nsk_printHexBytes(" ", 16, class_data_len, class_data); 123 } 124 125 { 126 /*store original byte code, it will be used to do final redefinition*/ 127 int j; 128 unsigned char *arr; 129 130 oldClassDef[clsLoadedIdx].class_byte_count = class_data_len; 131 if (!NSK_JVMTI_VERIFY(jvmti_env->Allocate(class_data_len, &arr))) { 132 nsk_jvmti_setFailStatus(); 133 return; 134 } 135 for (j = 0; j < class_data_len; j++) { 136 arr[j] = class_data[j]; 137 } 138 oldClassDef[clsLoadedIdx].class_bytes = arr; 139 } 140 141 *new_class_data_len = newClassSize[clsLoadedIdx]; 142 *new_class_data = newClassBytes[clsLoadedIdx]; 143 144 NSK_DISPLAY2("Replace with new bytecode: 0x%p:%d\n", 145 (void*)newClassBytes[clsLoadedIdx], 146 (int)newClassSize[clsLoadedIdx]); 147 if (nsk_getVerboseMode()) { 148 nsk_printHexBytes(" ", 16, newClassSize[clsLoadedIdx], 149 newClassBytes[clsLoadedIdx]); 150 } 151 } 152 153 /* ============================================================================= */ 154 155 /** Agent algorithm. */ 156 static void JNICALL 157 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { 158 159 int i; 160 161 /*Wait for debuggee to read new byte codes nsk_jvmti_waitForSync#1*/ 162 NSK_DISPLAY0("Wait for debuggee to read new byte codes nsk_jvmti_waitForSync#1\n"); 163 if (!nsk_jvmti_waitForSync(timeout)) 164 return; 165 166 for (clsLoadedIdx=0; clsLoadedIdx < TOTAL_INSTRUMENTED_CLASSES; clsLoadedIdx++) { 167 168 if (!nsk_jvmti_resumeSync()) 169 return; 170 171 NSK_DISPLAY1("Wait for debuggee to load tested class by classLoader[%d]\n", 172 (clsLoadedIdx+1)); 173 /*Wait for debuggee to load next class nsk_jvmti_waitForSync#2*/ 174 if (!nsk_jvmti_waitForSync(timeout)) 175 return; 176 } 177 178 if (!nsk_jvmti_resumeSync()) 179 return; 180 181 /*Wait for debuggee to check instrumentation code works nsk_jvmti_waitForSync#3*/ 182 NSK_DISPLAY0("Wait for debuggee to check instrumentation code works nsk_jvmti_waitForSync#3\n"); 183 if (!nsk_jvmti_waitForSync(timeout)) 184 return; 185 186 NSK_DISPLAY0("Notification disabled for CLASS_FILE_LOAD_HOOK event\n"); 187 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_DISABLE, 188 JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, 189 NULL))) { 190 nsk_jvmti_setFailStatus(); 191 return; 192 } 193 194 if (!nsk_jvmti_resumeSync()) 195 return; 196 197 /*Wait for debuggee to set classes to be redefined nsk_jvmti_waitForSync#4*/ 198 NSK_DISPLAY0("Wait for debuggee to set classes to be redefined nsk_jvmti_waitForSync#4\n"); 199 if (!nsk_jvmti_waitForSync(timeout)) 200 return; 201 202 NSK_DISPLAY0("Redfine class with old byte code\n"); 203 for (i = 0; i < TOTAL_INSTRUMENTED_CLASSES; i++) { 204 NSK_DISPLAY4("class definition %d:\n\t0x%p, 0x%p:%d\n", 205 i, 206 oldClassDef[i].klass, 207 oldClassDef[i].class_bytes, 208 oldClassDef[i].class_byte_count); 209 if (nsk_getVerboseMode()) { 210 nsk_printHexBytes(" ", 16, oldClassDef[i].class_byte_count, 211 oldClassDef[i].class_bytes); 212 } 213 } 214 if (!NSK_JVMTI_VERIFY(jvmti->RedefineClasses(TOTAL_INSTRUMENTED_CLASSES, oldClassDef))) { 215 nsk_jvmti_setFailStatus(); 216 return; 217 } 218 219 if (!nsk_jvmti_resumeSync()) 220 return; 221 222 /*Wait for debuggee to check old byte code works nsk_jvmti_waitForSync#5*/ 223 NSK_DISPLAY0("Wait for debuggee to check old byte code works nsk_jvmti_waitForSync#5\n"); 224 if (!nsk_jvmti_waitForSync(timeout)) 225 return; 226 227 for (i = 0; i < TOTAL_INSTRUMENTED_CLASSES; i++) { 228 agentJNI->DeleteGlobalRef(oldClassDef[i].klass); 229 } 230 231 NSK_DISPLAY0("Let debuggee to finish\n"); 232 if (!nsk_jvmti_resumeSync()) 233 return; 234 235 } 236 237 /* ============================================================================= */ 238 239 /** Agent library initialization. */ 240 #ifdef STATIC_BUILD 241 JNIEXPORT jint JNICALL Agent_OnLoad_bi01t002(JavaVM *jvm, char *options, void *reserved) { 242 return Agent_Initialize(jvm, options, reserved); 243 } 244 JNIEXPORT jint JNICALL Agent_OnAttach_bi01t002(JavaVM *jvm, char *options, void *reserved) { 245 return Agent_Initialize(jvm, options, reserved); 246 } 247 JNIEXPORT jint JNI_OnLoad_bi01t002(JavaVM *jvm, char *options, void *reserved) { 248 return JNI_VERSION_1_8; 249 } 250 #endif 251 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 252 253 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 254 return JNI_ERR; 255 256 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 257 258 if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 259 return JNI_ERR; 260 261 { 262 jvmtiCapabilities caps; 263 memset(&caps, 0, sizeof(caps)); 264 265 caps.can_redefine_classes = 1; 266 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) 267 return JNI_ERR; 268 } 269 270 NSK_DISPLAY0("Set callback for CLASS_FILE_LOAD_HOOK event\n"); 271 { 272 jvmtiEventCallbacks callbacks; 273 jint size = (jint)sizeof(callbacks); 274 275 memset(&callbacks, 0, size); 276 callbacks.ClassFileLoadHook = cbClassFileLoadHook; 277 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, size))) { 278 return JNI_ERR; 279 } 280 } 281 282 NSK_DISPLAY0("Set notification enabled for CLASS_FILE_LOAD_HOOK event\n"); 283 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, 284 JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, 285 NULL))) { 286 nsk_jvmti_setFailStatus(); 287 return NSK_FALSE; 288 } 289 290 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 291 return JNI_ERR; 292 293 return JNI_OK; 294 } 295 296 /* ============================================================================= */ 297 298 299 }