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 <jvmti.h> 25 #include "agent_common.h" 26 #include <jni.h> 27 #include <string.h> 28 #include "jvmti_tools.h" 29 #include "JVMTITools.h" 30 31 /* 32 T002: 33 1. Set a breakpoint in method b(). 34 2. Call method a() which calls b(). 35 Upon reaching the breakpoint, enable SingleStep. 36 3. Redefine class within SingleStep callback. New class version 37 contains the same method b() and the changed method a(). Stepping 38 should be continued in the method b(). 39 4. Pop a currently executed frame. Stepping should be continued 40 on invoke instruction of the obsolete method a(). 41 5. Pop a frame once more. Stepping should be continued 42 on invoke instruction of main method and then in the changed 43 method b(). 44 */ 45 46 extern "C" { 47 48 #define FILE_NAME "nsk/jvmti/scenarios/hotswap/HS203/hs203t002/MyThread" 49 #define SEARCH_NAME "nsk/jvmti/scenarios/hotswap/HS203/hs203t002/MyThread" 50 #define METHOD_NAME "doTask2" 51 #define METHOD_SIGN "()V" 52 #define CLASS_NAME "Lnsk/jvmti/scenarios/hotswap/HS203/hs203t002/MyThread;" 53 static jint redefineNumber; 54 static jvmtiEnv * jvmti; 55 56 JNIEXPORT void JNICALL 57 callbackClassLoad(jvmtiEnv *jvmti, 58 JNIEnv* jni, 59 jthread thread, 60 jclass klass) { 61 char * className; 62 char * generic; 63 redefineNumber=0; 64 jvmti->GetClassSignature(klass, &className, &generic); 65 if (strcmp(className,CLASS_NAME) == 0) { 66 jmethodID method; 67 method = jni->GetMethodID(klass,METHOD_NAME,METHOD_SIGN); 68 if (method != NULL) { 69 jlocation start; 70 jlocation end; 71 jvmtiError err ; 72 err=jvmti->GetMethodLocation(method, &start, &end); 73 if (err == JVMTI_ERROR_NONE) { 74 nsk_printf("Agent:: NO ERRORS FOUND \n"); 75 err= jvmti->SetBreakpoint(method, start); 76 if (err == JVMTI_ERROR_NONE) { 77 nsk_printf("Agent:: Breakpoint set \n"); 78 } else { 79 nsk_printf("Agent:: ***ERROR OCCURED ... in SET BREAK POINT ERROR \n"); 80 } 81 } else { 82 nsk_printf("Agent:: ***ERROR OCCURED .. in METHOD LOCATION FINDER \n"); 83 } 84 } else { 85 nsk_printf("Agent:: ***ERROR OCCURED .. COUND NOT FIND THE METHOD AND SIGNATURE SPECIFIED \n"); 86 } 87 } 88 } 89 90 void JNICALL callbackSingleStep(jvmtiEnv *jvmti, 91 JNIEnv* jni, jthread thread, 92 jmethodID method, jlocation location) { 93 jclass threadClass; 94 jvmtiError err; 95 char fileName[512]; 96 97 threadClass = jni->FindClass(SEARCH_NAME); 98 nsk_printf(" %d..",redefineNumber); 99 nsk_jvmti_getFileName(redefineNumber, FILE_NAME, fileName, sizeof(fileName)/sizeof(char)); 100 101 if(nsk_jvmti_redefineClass(jvmti, threadClass,fileName) == NSK_TRUE) { 102 nsk_printf("Agent:: Redefined..\n"); 103 } else { 104 nsk_printf(" Failed to redefine..\n"); 105 return; 106 } 107 err=jvmti->SuspendThread(thread); 108 if (err == JVMTI_ERROR_NONE) { 109 nsk_printf("Agent:: Succeded in suspending..\n"); 110 } else { 111 nsk_printf(" ## Error occured %s \n",TranslateError(err)); 112 } 113 } 114 115 void JNICALL callbackBreakpoint(jvmtiEnv *jvmti, 116 JNIEnv* jni, 117 jthread thread, 118 jmethodID method, 119 jlocation location) { 120 nsk_printf("Agent::... BreakPoint Reached..\n"); 121 if (nsk_jvmti_enableNotification(jvmti,JVMTI_EVENT_SINGLE_STEP,thread) == JNI_OK) { 122 nsk_printf(" .... Enabled..\n"); 123 } 124 return; 125 } 126 127 128 #ifdef STATIC_BUILD 129 JNIEXPORT jint JNICALL Agent_OnLoad_hs203t002(JavaVM *jvm, char *options, void *reserved) { 130 return Agent_Initialize(jvm, options, reserved); 131 } 132 JNIEXPORT jint JNICALL Agent_OnAttach_hs203t002(JavaVM *jvm, char *options, void *reserved) { 133 return Agent_Initialize(jvm, options, reserved); 134 } 135 JNIEXPORT jint JNI_OnLoad_hs203t002(JavaVM *jvm, char *options, void *reserved) { 136 return JNI_VERSION_1_8; 137 } 138 #endif 139 jint Agent_Initialize(JavaVM *vm, char *options, void *reserved) { 140 jint rc ; 141 nsk_printf("Agent:: VM.. Started..\n"); 142 rc=vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1); 143 if (rc!= JNI_OK) { 144 nsk_printf("Agent:: Could not load JVMTI interface \n"); 145 return JNI_ERR; 146 } else { 147 jvmtiCapabilities caps; 148 jvmtiEventCallbacks eventCallbacks; 149 if (nsk_jvmti_parseOptions(options) == NSK_FALSE) { 150 nsk_printf("# error agent Failed to parse options \n"); 151 return JNI_ERR; 152 } 153 memset(&caps, 0, sizeof(caps)); 154 caps.can_redefine_classes = 1; 155 caps.can_suspend=1; 156 caps.can_pop_frame=1; 157 caps.can_generate_breakpoint_events=1; 158 caps.can_generate_all_class_hook_events=1; 159 caps.can_generate_single_step_events=1; 160 jvmti->AddCapabilities(&caps); 161 162 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 163 eventCallbacks.ClassLoad =callbackClassLoad; 164 eventCallbacks.Breakpoint = callbackBreakpoint; 165 eventCallbacks.SingleStep =callbackSingleStep; 166 rc=jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)); 167 if (rc != JVMTI_ERROR_NONE) { 168 nsk_printf(" Agent:: Error occured while setting event call back \n"); 169 return JNI_ERR; 170 } 171 if ((nsk_jvmti_enableNotification(jvmti,JVMTI_EVENT_CLASS_LOAD, 172 NULL) == NSK_TRUE) && 173 (nsk_jvmti_enableNotification(jvmti,JVMTI_EVENT_BREAKPOINT, 174 NULL) == NSK_TRUE)) { 175 nsk_printf("Agent :: NOTIFICATIONS ARE ENABLED \n"); 176 } else { 177 nsk_printf(" Error in Eanableing Notifications.."); 178 } 179 } 180 return JNI_OK; 181 } 182 183 184 JNIEXPORT jboolean JNICALL 185 Java_nsk_jvmti_scenarios_hotswap_HS203_hs203t002_hs203t002_popThreadFrame(JNIEnv * jni, 186 jclass clas, 187 jthread thread) { 188 jvmtiError err ; 189 jboolean retvalue; 190 jint state; 191 nsk_printf("Agent:: POPING THE FRAME....\n"); 192 retvalue = JNI_FALSE; 193 jvmti->GetThreadState(thread, &state); 194 if (state & JVMTI_THREAD_STATE_SUSPENDED) { 195 err = jvmti->PopFrame(thread); 196 if (err == JVMTI_ERROR_NONE) { 197 nsk_printf("Agent:: NO Errors poped very well ..\n"); 198 retvalue = JNI_TRUE; 199 } else { 200 nsk_printf(" ## Error occured %s \n",TranslateError(err)); 201 } 202 } else { 203 nsk_printf("Agent:: Thread was not suspened.. check for capabilities, and java method signature \n"); 204 } 205 return retvalue; 206 } 207 208 JNIEXPORT jboolean JNICALL 209 Java_nsk_jvmti_scenarios_hotswap_HS203_hs203t002_hs203t002_resumeThread(JNIEnv * jni, 210 jclass clas, 211 jthread thread) { 212 jvmtiError err ; 213 jboolean retvalue; 214 retvalue = JNI_FALSE; 215 err =jvmti->SetEventNotificationMode(JVMTI_DISABLE,JVMTI_EVENT_SINGLE_STEP,thread); 216 if (err == JVMTI_ERROR_NONE) { 217 nsk_printf(" Agent:: cleared Single Step event"); 218 } else { 219 nsk_printf(" Agent :: Failed to clear Single Step Event"); 220 } 221 err =jvmti->SetEventNotificationMode(JVMTI_DISABLE,JVMTI_EVENT_BREAKPOINT,thread); 222 if (err == JVMTI_ERROR_NONE) { 223 nsk_printf(" Agent:: cleared Break point event"); 224 } else { 225 nsk_printf(" Agent :: Failed to clear Single Step Event"); 226 } 227 err = jvmti->ResumeThread(thread); 228 if (err == JVMTI_ERROR_NONE) { 229 nsk_printf(" Agent:: Thread Resumed.."); 230 } else { 231 nsk_printf(" Failed.. to Resume the thread."); 232 } 233 return retvalue; 234 } 235 236 JNIEXPORT jboolean JNICALL 237 Java_nsk_jvmti_scenarios_hotswap_HS203_hs203t002_hs203t002_suspendThread(JNIEnv * jni, 238 jclass clas, 239 jthread thread) { 240 jvmtiError err ; 241 jboolean retvalue; 242 retvalue = JNI_FALSE; 243 err = jvmti->SuspendThread(thread); 244 if (err == JVMTI_ERROR_NONE) { 245 nsk_printf(" Agent:: Thread suspended.."); 246 retvalue= JNI_TRUE; 247 } else { 248 nsk_printf(" ## Error occured %s \n",TranslateError(err)); 249 } 250 return retvalue; 251 } 252 253 }