1 /* 2 * Copyright (c) 2007, 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 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <jvmti.h> 27 #include "agent_common.h" 28 #include <jni.h> 29 #include "jvmti_tools.h" 30 #include "jni_tools.h" 31 #include "JVMTITools.h" 32 33 extern "C" { 34 35 #define FILE_NAME "nsk/jvmti/scenarios/hotswap/HS204/hs204t003/MyThread" 36 #define CLASS_NAME "Lnsk/jvmti/scenarios/hotswap/HS204/hs204t003/MyThread;" 37 #define FIELDNAME "intState" 38 #define TYPE "I" 39 40 static jint redefineNumber; 41 static jvmtiEnv * jvmti; 42 static jclass watchFieldClass; 43 44 JNIEXPORT void JNICALL callbackClassPrepare(jvmtiEnv *jvmti_env, 45 JNIEnv* jni, 46 jthread thread, 47 jclass klass) { 48 char * className; 49 char * generic; 50 51 className = NULL; 52 generic = NULL; 53 redefineNumber=0; 54 if ( !NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, jvmti_env, 55 klass, &className, &generic)) ) { 56 NSK_DISPLAY0(" Agent :: Failed get class signature.\n"); 57 nsk_jvmti_agentFailed(); 58 } else { 59 if( (strcmp(className, CLASS_NAME) == 0 ) ) { 60 jfieldID fieldId; 61 if ( ! NSK_JNI_VERIFY(jni, (fieldId = NSK_CPP_STUB4(GetStaticFieldID, 62 jni, klass, FIELDNAME, TYPE) ) != NULL ) ) { 63 NSK_DISPLAY0(" Agent :: Failed to get FieldId.\n"); 64 nsk_jvmti_agentFailed(); 65 } else { 66 if ( ! NSK_JVMTI_VERIFY( NSK_CPP_STUB3(SetFieldAccessWatch, 67 jvmti_env, klass, fieldId) ) ) { 68 NSK_DISPLAY0(" Agent :: Failed to set watch point on a field.\n"); 69 nsk_jvmti_agentFailed(); 70 } else { 71 nsk_jvmti_enableNotification(jvmti_env, JVMTI_EVENT_FIELD_ACCESS, NULL); 72 if (! NSK_JNI_VERIFY(jni, 73 ( watchFieldClass = (jclass) 74 NSK_CPP_STUB2(NewGlobalRef, jni, klass) ) 75 != NULL ) ) { 76 NSK_DISPLAY0(" Agent :: Failed to get global reference for class.\n"); 77 nsk_jvmti_agentFailed(); 78 } 79 NSK_DISPLAY0(" Agent :: SetFieldAccessWatch.\n"); 80 } 81 } 82 NSK_DISPLAY1(" Agent :: Leaving callbackClassPrepare for class = %s .\n", className); 83 } 84 } 85 86 if ( className != NULL ) { 87 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char *)className))) { 88 NSK_DISPLAY1(" Agent :: #error failed to Deallocate className = %s.", className); 89 nsk_jvmti_agentFailed(); 90 } 91 } 92 93 if ( generic != NULL ) { 94 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char *)generic))) { 95 NSK_DISPLAY1(" Agent :: #error failed to Deallocate class signature = %s.", generic); 96 nsk_jvmti_agentFailed(); 97 } 98 } 99 return; 100 } 101 102 JNIEXPORT void JNICALL callbackFieldAccess(jvmtiEnv *jvmti_env, 103 JNIEnv* jni, 104 jthread thread, 105 jmethodID method, 106 jlocation location, 107 jclass field_klass, 108 jobject object, 109 jfieldID field) { 110 char fileName[512]; 111 char * className; 112 char * generic; 113 114 className = NULL; 115 generic = NULL; 116 if (redefineNumber != 0 ) { 117 return; 118 } 119 if ( ! NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, jvmti_env, 120 field_klass, &className, &generic)) ) { 121 NSK_DISPLAY0(" Agent :: Failed get class signature.\n"); 122 nsk_jvmti_agentFailed(); 123 } else { 124 if( (strcmp(className, CLASS_NAME) == 0 ) ) { 125 jvmtiThreadInfo info; 126 nsk_jvmti_getFileName(redefineNumber, FILE_NAME, fileName, 127 sizeof(fileName)/sizeof(char)); 128 if ( nsk_jvmti_redefineClass(jvmti_env, field_klass, fileName) == NSK_TRUE ) { 129 NSK_DISPLAY0(" Agent :: Successfully redefined.\n"); 130 redefineNumber++; 131 } else { 132 NSK_DISPLAY0(" Agent :: Failed to redefine.\n"); 133 nsk_jvmti_agentFailed(); 134 } 135 NSK_DISPLAY0(" Agent :: Before attempting thread suspend.\n"); 136 if ( ! NSK_JVMTI_VERIFY( NSK_CPP_STUB3(GetThreadInfo, jvmti_env, thread , &info)) ) { 137 NSK_DISPLAY0(" Agent :: error getting thread info "); 138 nsk_jvmti_agentFailed(); 139 } else { 140 NSK_DISPLAY1(" Agent :: Thread Name = %s .\n", info.name); 141 } 142 if ( ! NSK_JVMTI_VERIFY( NSK_CPP_STUB2(SuspendThread, jvmti_env, thread)) ) { 143 NSK_DISPLAY0(" Agent :: Failed to suspend thread.\n"); 144 nsk_jvmti_agentFailed(); 145 } 146 } 147 } 148 149 if ( className != NULL ) { 150 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char *)className))) { 151 NSK_DISPLAY1(" Agent :: #error failed to Deallocate className = %s.", className); 152 nsk_jvmti_agentFailed(); 153 } 154 } 155 156 if ( generic != NULL ) { 157 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char *)generic))) { 158 NSK_DISPLAY1(" Agent :: #error failed to Deallocate class signature = %s.", generic); 159 nsk_jvmti_agentFailed(); 160 } 161 } 162 } 163 164 #ifdef STATIC_BUILD 165 JNIEXPORT jint JNICALL Agent_OnLoad_hs204t003(JavaVM *jvm, char *options, void *reserved) { 166 return Agent_Initialize(jvm, options, reserved); 167 } 168 JNIEXPORT jint JNICALL Agent_OnAttach_hs204t003(JavaVM *jvm, char *options, void *reserved) { 169 return Agent_Initialize(jvm, options, reserved); 170 } 171 JNIEXPORT jint JNI_OnLoad_hs204t003(JavaVM *jvm, char *options, void *reserved) { 172 return JNI_VERSION_1_8; 173 } 174 #endif 175 jint Agent_Initialize(JavaVM *vm, char *options, void *reserved) { 176 if ( ! NSK_VERIFY ( JNI_OK == NSK_CPP_STUB3(GetEnv, vm, 177 (void **)&jvmti, JVMTI_VERSION_1_1) ) ) { 178 NSK_DISPLAY0("Agent :: Could not load JVMTI interface \n"); 179 return JNI_ERR; 180 } else { 181 jvmtiCapabilities caps; 182 jvmtiEventCallbacks eventCallbacks; 183 memset(&caps, 0, sizeof(caps)); 184 if (!nsk_jvmti_parseOptions(options)) { 185 NSK_DISPLAY0(" NSK Failed to parse.."); 186 return JNI_ERR; 187 } 188 caps.can_redefine_classes = 1; 189 caps.can_generate_field_access_events = 1; 190 caps.can_pop_frame = 1; 191 caps.can_suspend = 1; 192 if ( ! NSK_JVMTI_VERIFY(NSK_CPP_STUB2( AddCapabilities, jvmti, &caps)) ) { 193 NSK_DISPLAY0(" Agent :: Failed add required capabilities\n."); 194 return JNI_ERR; 195 } 196 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 197 eventCallbacks.ClassPrepare = callbackClassPrepare; 198 eventCallbacks.FieldAccess = callbackFieldAccess; 199 if (!NSK_JVMTI_VERIFY( NSK_CPP_STUB3(SetEventCallbacks, jvmti, 200 &eventCallbacks, sizeof(eventCallbacks) ) ) ) { 201 NSK_DISPLAY0(" Agent :: Error occured while setting event call back \n"); 202 return JNI_ERR; 203 } 204 nsk_jvmti_enableNotification(jvmti, JVMTI_EVENT_CLASS_PREPARE, NULL); 205 } 206 return JNI_OK; 207 } 208 209 JNIEXPORT jboolean JNICALL 210 Java_nsk_jvmti_scenarios_hotswap_HS204_hs204t003_hs204t003_popFrame(JNIEnv * jni, 211 jobject object, 212 jthread thread) { 213 jboolean retvalue; 214 jint state; 215 retvalue = JNI_FALSE; 216 if (! NSK_JVMTI_VERIFY( NSK_CPP_STUB3(GetThreadState, jvmti, thread, &state)) ){ 217 NSK_DISPLAY0(" Agent :: Error getting thread state.\n"); 218 nsk_jvmti_agentFailed(); 219 } else { 220 if ( state & JVMTI_THREAD_STATE_SUSPENDED) { 221 NSK_DISPLAY0(" Agent :: Thread state = JVMTI_THREAD_STATE_SUSPENDED.\n"); 222 if ( ! NSK_JVMTI_VERIFY ( NSK_CPP_STUB2(PopFrame, jvmti, thread) ) ) { 223 NSK_DISPLAY0("#error Agent :: Jvmti failed to do popFrame.\n"); 224 nsk_jvmti_agentFailed(); 225 } else { 226 if ( ! NSK_JVMTI_VERIFY ( NSK_CPP_STUB2(ResumeThread, jvmti, thread)) ) { 227 NSK_DISPLAY0(" Agent :: Error occured in resuming a thread.\n"); 228 nsk_jvmti_agentFailed(); 229 } else { 230 jfieldID fieldId; 231 if ( ! NSK_JNI_VERIFY(jni, (fieldId = NSK_CPP_STUB4(GetStaticFieldID, 232 jni, watchFieldClass, FIELDNAME, TYPE) ) != NULL ) ) { 233 NSK_DISPLAY0(" Agent :: Failed to get FieldId before droping watchers.\n"); 234 nsk_jvmti_agentFailed(); 235 } else { 236 if ( ! NSK_JVMTI_VERIFY ( NSK_CPP_STUB3(ClearFieldAccessWatch, 237 jvmti, watchFieldClass, fieldId)) ) { 238 NSK_DISPLAY0(" Agent :: failed to drop field watces.\n"); 239 nsk_jvmti_agentFailed(); 240 } else { 241 NSK_DISPLAY0(" Agent :: Sucessfully droped watches.\n"); 242 retvalue = JNI_TRUE; 243 } 244 } 245 } 246 } 247 } else { 248 NSK_DISPLAY0(" Agent :: Thread should be suspended to its pop frame.\n"); 249 } 250 } 251 return retvalue; 252 } 253 }