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