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