1 /* 2 * Copyright (c) 2007, 2019, 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 <jni.h> 24 #include <jvmti.h> 25 #include "agent_common.h" 26 #include <string.h> 27 #include "jvmti_tools.h" 28 #include "JVMTITools.h" 29 /* 30 hs202t001: 31 1. Set breakpoints in several methods when Object.wait(), 32 Object.notify(), Object.notifyAll() are in use in these methods. 33 2. Upon reaching a breakpoint, enable SingleStep. 34 3. Redefine an java.lang.Object class within SingleStep callback 35 when one of its methods is called by the tested method. 36 4. Pop a currently executed frame. 37 38 */ 39 extern "C" { 40 #define FILE_NAME "nsk/jvmti/scenarios/hotswap/HS202/hs203t001/MyObject" 41 #define CLASS_NAME "Lnsk/jvmti/scenarios/hotswap/HS202/hs203t001/MyObject;" 42 #define METHOD_NAME "leaveMonitor" 43 #define METHOD_SIGN "()V" 44 #define METHOD_NOTIFYALL "notifyAll" 45 46 static jvmtiEnv * jvmti; 47 48 49 JNIEXPORT void JNICALL callbackClassPrepare(jvmtiEnv *jvmti, 50 JNIEnv* jni, 51 jthread thread, 52 jclass klass) { 53 char * className; 54 char * generic; 55 jvmti->GetClassSignature(klass, &className, &generic); 56 if (strcmp(className,CLASS_NAME) == 0) { 57 jmethodID method; 58 method = jni->GetMethodID(klass, METHOD_NAME, METHOD_SIGN); 59 if (method == NULL) { 60 nsk_printf("Agent:: Method is null "); 61 } else { 62 jlocation start; 63 jlocation end; 64 jvmtiError err ; 65 err=jvmti->GetMethodLocation(method, &start, &end); 66 if (err != JVMTI_ERROR_NONE) { 67 nsk_printf(" ## Error occured %s \n",TranslateError(err)); 68 }else { 69 nsk_printf("\n Start = %d and end = %d ", start , end); 70 nsk_printf(" setting break points.."); 71 err= jvmti->SetBreakpoint(method, start); 72 if (err != JVMTI_ERROR_NONE) { 73 nsk_printf(" ## Error occured %s \n",TranslateError(err)); 74 } else { 75 nsk_printf(" NO ERRORS "); 76 if (nsk_jvmti_enableNotification(jvmti,JVMTI_EVENT_BREAKPOINT, NULL) == NSK_TRUE) { 77 nsk_printf(" Enabled.. notification event ..\n"); 78 } 79 } 80 } 81 } 82 } 83 } 84 85 /* 86 *This event call back will be called when a filed 87 *threadState is beeing upodated or beeing used in 88 *the program java flow. 89 *In this current example the code will be called 90 */ 91 void JNICALL callbackSingleStep(jvmtiEnv *jvmti_env, 92 JNIEnv* jni, 93 jthread thread, 94 jmethodID method, 95 jlocation location) { 96 jvmtiError err; 97 char * name; 98 char * signature; 99 char * generic ; 100 err = JVMTI_ERROR_NONE; 101 jvmti_env->GetMethodName(method, &name, &signature, &generic); 102 if (strcmp(name,METHOD_NAME) == 0) { /* same method */ 103 jclass cls; 104 jmethodID mem ; 105 jvmti_env->GetMethodDeclaringClass(method, &cls); 106 mem=jni->GetMethodID(cls,METHOD_NOTIFYALL,"()V"); 107 jni->CallVoidMethod(thread,mem); 108 } 109 110 } 111 112 void JNICALL callbackBreakpoint(jvmtiEnv *jvmti_env, 113 JNIEnv* jni_env, 114 jthread thread, 115 jmethodID method, 116 jlocation location) { 117 jvmtiError err; 118 err = JVMTI_ERROR_NONE; 119 if (nsk_jvmti_enableNotification(jvmti,JVMTI_EVENT_SINGLE_STEP, NULL) == NSK_TRUE) { 120 nsk_printf(" Enabled.. notification event .."); 121 } 122 err= jvmti->SetEventNotificationMode(JVMTI_DISABLE, 123 JVMTI_EVENT_BREAKPOINT, NULL); 124 if (err == JVMTI_ERROR_NONE) { 125 nsk_printf(" Disabled notification.."); 126 } 127 128 } 129 130 131 #ifdef STATIC_BUILD 132 JNIEXPORT jint JNICALL Agent_OnLoad_hs202t001(JavaVM *jvm, char *options, void *reserved) { 133 return Agent_Initialize(jvm, options, reserved); 134 } 135 JNIEXPORT jint JNICALL Agent_OnAttach_hs202t001(JavaVM *jvm, char *options, void *reserved) { 136 return Agent_Initialize(jvm, options, reserved); 137 } 138 JNIEXPORT jint JNI_OnLoad_hs202t001(JavaVM *jvm, char *options, void *reserved) { 139 return JNI_VERSION_1_8; 140 } 141 #endif 142 jint Agent_Initialize(JavaVM *vm, char *options, void *reserved) { 143 jvmtiError rc; 144 jint code; 145 nsk_printf("Agent:: VM.. Started..\n"); 146 code = vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_1); 147 if (code != JNI_OK) { 148 nsk_printf("Agent:: Could not load JVMTI interface \n"); 149 return JNI_ERR; 150 } else { 151 jvmtiCapabilities caps; 152 jvmtiEventCallbacks eventCallbacks; 153 memset(&caps, 0, sizeof(caps)); 154 if (!nsk_jvmti_parseOptions(options)) { 155 nsk_printf("# error agent Failed to parse options \n"); 156 return JNI_ERR; 157 } 158 caps.can_redefine_classes = 1; 159 caps.can_suspend = 1; 160 caps.can_pop_frame = 1; 161 caps.can_generate_all_class_hook_events = 1; 162 caps.can_generate_compiled_method_load_events = 1; 163 caps.can_generate_breakpoint_events=1; 164 caps.can_generate_single_step_events=1; 165 jvmti->AddCapabilities(&caps); 166 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 167 eventCallbacks.ClassPrepare =callbackClassPrepare; 168 eventCallbacks.SingleStep =callbackSingleStep; 169 eventCallbacks.Breakpoint =callbackBreakpoint; 170 rc = jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)); 171 if (rc != JVMTI_ERROR_NONE) { 172 nsk_printf(" ## Error occured %s \n",TranslateError(rc)); 173 return JNI_ERR; 174 } 175 if (nsk_jvmti_enableNotification(jvmti,JVMTI_EVENT_CLASS_PREPARE, NULL) == NSK_TRUE) { 176 nsk_printf("Agent :: NOTIFICATIONS ARE ENABLED \n"); 177 } else { 178 nsk_printf(" Error in Eanableing Notifications.."); 179 } 180 } 181 return JNI_OK; 182 } 183 184 JNIEXPORT jboolean JNICALL 185 Java_nsk_jvmti_scenarios_hotswap_HS202_hs202t001_hs202t001_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_OK; 199 return retvalue; 200 } else if (err != JVMTI_ERROR_NONE) { 201 nsk_printf(" ## Error occured %s \n",TranslateError(err)); 202 } 203 nsk_printf("Agent:: some other error ..\n"); 204 } else { 205 nsk_printf("Agent:: Thread was not suspened.. check for capabilities, and java method signature "); 206 } 207 return retvalue; 208 } 209 210 JNIEXPORT jboolean JNICALL 211 Java_nsk_jvmti_scenarios_hotswap_HS202_hs202t001_hs202t001_resumeThread(JNIEnv * jni, 212 jclass clas, 213 jthread thread) { 214 jvmtiError err ; 215 jboolean retvalue; 216 retvalue = JNI_FALSE; 217 err = jvmti->ResumeThread(thread); 218 if (err == JVMTI_ERROR_NONE) { 219 nsk_printf(" Agent:: Thread Resumed.. \n"); 220 retvalue=JNI_OK; 221 } else { 222 nsk_printf(" Agent:: Failed.. to Resume the thread.\n"); 223 } 224 return retvalue; 225 } 226 227 }