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 <jvmti.h> 26 #include "agent_common.h" 27 #include <jni.h> 28 #include <string.h> 29 #include "jvmti_tools.h" 30 #include "JVMTITools.h" 31 #include "jni_tools.h" 32 33 extern "C" { 34 #define FILE_NAME "nsk/jvmti/scenarios/hotswap/HS203/hs203t004/MyThread" 35 #define CLASS_NAME "Lnsk/jvmti/scenarios/hotswap/HS203/hs203t004/MyThread;" 36 #define METHOD_NAME "doTask2" 37 38 static jint redefineNumber; 39 static jvmtiEnv * jvmti; 40 41 JNIEXPORT void JNICALL callbackClassPrepare(jvmtiEnv *jvmti_env, 42 JNIEnv* jni, 43 jthread thread, 44 jclass klass) { 45 char * className; 46 className=NULL; 47 48 if (!NSK_JVMTI_VERIFY (NSK_CPP_STUB4(GetClassSignature, 49 jvmti_env, klass, &className, NULL) ) ) { 50 NSK_COMPLAIN0("#error Agent :: while getting classname.\n"); 51 nsk_jvmti_agentFailed(); 52 } else { 53 if (strcmp(className, CLASS_NAME) == 0) { 54 if (nsk_jvmti_enableNotification(jvmti_env, JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL) == NSK_TRUE ) { 55 NSK_DISPLAY0(" Agent :: notification enabled for COMPILED_METHOD_LOAD.\n"); 56 if ( ! NSK_JVMTI_VERIFY ( NSK_CPP_STUB2(GenerateEvents, jvmti_env, 57 JVMTI_EVENT_COMPILED_METHOD_LOAD ) )) { 58 NSK_COMPLAIN0("#error Agent :: occured while enabling compiled method events.\n"); 59 nsk_jvmti_agentFailed(); 60 } 61 } 62 } 63 64 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char *)className))) { 65 NSK_COMPLAIN1("#error Agent :: failed to Deallocate className = %s.", className); 66 nsk_jvmti_agentFailed(); 67 } 68 } 69 } 70 71 72 JNIEXPORT void JNICALL callbackCompiledMethodLoad(jvmtiEnv *jvmti_env, 73 jmethodID method, 74 jint code_size, 75 const void* code_addr, 76 jint map_length, 77 const jvmtiAddrLocationMap* map, 78 const void* compile_info) { 79 jclass threadClass; 80 if (redefineNumber == 0) { 81 if ( ! NSK_JVMTI_VERIFY ( NSK_CPP_STUB3(GetMethodDeclaringClass, 82 jvmti_env, method, &threadClass) ) ) { 83 NSK_COMPLAIN0("#error Agent :: while geting the declaring class.\n"); 84 nsk_jvmti_agentFailed(); 85 } else { 86 char *className; 87 char *methodName; 88 89 className = NULL; 90 methodName = NULL; 91 92 if ( ! NSK_JVMTI_VERIFY (NSK_CPP_STUB4(GetClassSignature, 93 jvmti_env, threadClass, &className, NULL) ) ) { 94 NSK_COMPLAIN0("#error Agent :: while getting classname.\n"); 95 nsk_jvmti_agentFailed(); 96 return; 97 } 98 99 if ( ! NSK_JVMTI_VERIFY (NSK_CPP_STUB5(GetMethodName, 100 jvmti_env, method, &methodName, NULL, NULL) ) ) { 101 NSK_COMPLAIN0("#error Agent :: while getting methodname.\n"); 102 nsk_jvmti_agentFailed(); 103 return; 104 } 105 106 if ((strcmp(className, CLASS_NAME) == 0) && (strcmp(methodName, METHOD_NAME) == 0)) { 107 char fileName[512]; 108 109 NSK_DISPLAY2(" Agent :: Got CompiledMethodLoadEvent for class: %s, method: %s.\n", className, methodName); 110 NSK_DISPLAY0(" Agent :: redefining class.\n"); 111 112 nsk_jvmti_getFileName(redefineNumber, FILE_NAME, fileName, sizeof(fileName)/sizeof(char)); 113 114 if ( nsk_jvmti_redefineClass(jvmti_env, threadClass, fileName) == NSK_TRUE) { 115 NSK_DISPLAY0(" Agent :: Successfully redefined.\n"); 116 redefineNumber++; 117 } else { 118 NSK_COMPLAIN0("#error Agent :: Failed to redefine.\n"); 119 nsk_jvmti_agentFailed(); 120 } 121 } 122 123 if ( className != NULL ) { 124 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char *)className))) { 125 NSK_COMPLAIN1("#error Agent :: failed to Deallocate className = %s.", className); 126 nsk_jvmti_agentFailed(); 127 } 128 } 129 if ( methodName != NULL ) { 130 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char *)methodName))) { 131 NSK_COMPLAIN1("#error Agent :: failed to Deallocate methodName = %s.", methodName); 132 nsk_jvmti_agentFailed(); 133 } 134 } 135 } 136 } 137 } 138 139 #ifdef STATIC_BUILD 140 JNIEXPORT jint JNICALL Agent_OnLoad_hs203t004(JavaVM *jvm, char *options, void *reserved) { 141 return Agent_Initialize(jvm, options, reserved); 142 } 143 JNIEXPORT jint JNICALL Agent_OnAttach_hs203t004(JavaVM *jvm, char *options, void *reserved) { 144 return Agent_Initialize(jvm, options, reserved); 145 } 146 JNIEXPORT jint JNI_OnLoad_hs203t004(JavaVM *jvm, char *options, void *reserved) { 147 return JNI_VERSION_1_8; 148 } 149 #endif 150 jint Agent_Initialize(JavaVM *vm, char *options, void *reserved) { 151 redefineNumber=0; 152 if ( ! NSK_VERIFY ( JNI_OK == NSK_CPP_STUB3(GetEnv, vm, 153 (void **)&jvmti, JVMTI_VERSION_1_1) ) ) { 154 NSK_DISPLAY0("#error Agent :: Could not load JVMTI interface.\n"); 155 return JNI_ERR; 156 } else { 157 jvmtiCapabilities caps; 158 jvmtiEventCallbacks eventCallbacks; 159 memset(&caps, 0, sizeof(caps)); 160 if (nsk_jvmti_parseOptions(options) == NSK_FALSE ) { 161 NSK_DISPLAY0("#error Agent :: Failed to parse options.\n"); 162 return JNI_ERR; 163 } 164 caps.can_redefine_classes = 1; 165 caps.can_suspend = 1; 166 caps.can_pop_frame = 1; 167 caps.can_generate_all_class_hook_events = 1; 168 caps.can_generate_compiled_method_load_events = 1; 169 if (! NSK_JVMTI_VERIFY ( NSK_CPP_STUB2(AddCapabilities, jvmti, &caps) )) { 170 NSK_DISPLAY0("#error Agent :: occured while adding capabilities.\n"); 171 return JNI_ERR; 172 } 173 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 174 eventCallbacks.ClassPrepare =callbackClassPrepare; 175 eventCallbacks.CompiledMethodLoad=callbackCompiledMethodLoad; 176 if (!NSK_JVMTI_VERIFY( 177 NSK_CPP_STUB3(SetEventCallbacks, jvmti, 178 &eventCallbacks, sizeof(eventCallbacks)))) { 179 NSK_COMPLAIN0("#error Agent :: occured while setting event callback.\n"); 180 return JNI_ERR; 181 } 182 if ( nsk_jvmti_enableNotification(jvmti,JVMTI_EVENT_CLASS_PREPARE, NULL) == NSK_TRUE) { 183 NSK_DISPLAY0(" Agent :: Notifications are enabled.\n"); 184 } else { 185 NSK_COMPLAIN0("#error Agent :: Error in enableing Notifications.\n"); 186 return JNI_ERR; 187 } 188 } 189 return JNI_OK; 190 } 191 192 JNIEXPORT void JNICALL 193 Java_nsk_jvmti_scenarios_hotswap_HS203_hs203t004_hs203t004_suspendThread(JNIEnv * jni, 194 jobject clas, 195 jthread thread) { 196 NSK_DISPLAY0(" Agent :: Suspending Thread.\n"); 197 if ( NSK_JVMTI_VERIFY( NSK_CPP_STUB2(SuspendThread, jvmti, thread) ) ) { 198 NSK_DISPLAY0(" Agent :: Succeded in suspending.\n"); 199 } else { 200 NSK_COMPLAIN0("#error Agent :: occured while suspending thread.\n"); 201 nsk_jvmti_agentFailed(); 202 } 203 } 204 205 JNIEXPORT jboolean JNICALL 206 Java_nsk_jvmti_scenarios_hotswap_HS203_hs203t004_hs203t004_popThreadFrame(JNIEnv * jni, 207 jobject clas, 208 jthread thread) { 209 jboolean retvalue; 210 jint state; 211 212 NSK_DISPLAY0(" Agent :: nsk.jvmti.scenarios.hotswap.HS203.hs203t004.popThreadFrame(... ).\n"); 213 retvalue = JNI_FALSE; 214 if ( ! NSK_JVMTI_VERIFY ( NSK_CPP_STUB3(GetThreadState, jvmti, 215 thread, &state) ) ) { 216 NSK_COMPLAIN0("#error Agent :: while getting thread's state.\n"); 217 nsk_jvmti_agentFailed(); 218 } else { 219 if ( state & JVMTI_THREAD_STATE_SUSPENDED) { 220 if ( ! NSK_JVMTI_VERIFY( NSK_CPP_STUB2(PopFrame, jvmti, thread) ) ){ 221 NSK_DISPLAY0("#error Agent :: occured while poping thread's frame.\n"); 222 nsk_jvmti_agentFailed(); 223 } else { 224 if ( NSK_JVMTI_VERIFY( NSK_CPP_STUB4(SetEventNotificationMode, jvmti, 225 JVMTI_DISABLE, JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL) ) ) { 226 NSK_DISPLAY0(" Agent :: Disabled JVMTI_EVENT_COMPILED_METHOD_LOAD.\n"); 227 retvalue = JNI_TRUE; 228 } else { 229 NSK_COMPLAIN0("#error Agent :: Failed to disable JVMTI_EVENT_COMPILED_METHOD_LOAD.\n"); 230 nsk_jvmti_agentFailed(); 231 } 232 } 233 } else { 234 NSK_COMPLAIN0("#error Agent :: Thread was not suspened.\n"); 235 nsk_jvmti_agentFailed(); 236 } 237 } 238 return retvalue; 239 } 240 241 JNIEXPORT jboolean JNICALL 242 Java_nsk_jvmti_scenarios_hotswap_HS203_hs203t004_hs203t004_resumeThread(JNIEnv * jni, 243 jclass clas, 244 jthread thread) { 245 jboolean retvalue; 246 247 retvalue = JNI_FALSE; 248 if ( NSK_JVMTI_VERIFY ( NSK_CPP_STUB2(ResumeThread, jvmti, thread))) { 249 NSK_DISPLAY0(" Agent :: Thread resumed.\n"); 250 retvalue= JNI_TRUE; 251 } else { 252 NSK_COMPLAIN0("#error Agent :: Failed to resume the thread.\n"); 253 nsk_jvmti_agentFailed(); 254 } 255 return retvalue; 256 } 257 258 }