1 /* 2 * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of Oracle nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * This source code is provided to illustrate the usage of a given feature 34 * or technique and has been deliberately simplified. Additional steps 35 * required for a production-quality application, such as security checks, 36 * input validation and proper error handling, might not be present in 37 * this sample code. 38 */ 39 40 41 /* Example of using JVMTI events: 42 * JVMTI_EVENT_VM_INIT 43 * JVMTI_EVENT_VM_DEATH 44 * JVMTI_EVENT_THREAD_START 45 * JVMTI_EVENT_THREAD_END 46 * JVMTI_EVENT_MONITOR_CONTENDED_ENTER 47 * JVMTI_EVENT_MONITOR_WAIT 48 * JVMTI_EVENT_MONITOR_WAITED 49 * JVMTI_EVENT_OBJECT_FREE 50 */ 51 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 56 #include "jni.h" 57 #include "jvmti.h" 58 59 #include "agent_util.h" 60 61 #include "Monitor.hpp" 62 #include "Thread.hpp" 63 #include "Agent.hpp" 64 65 static jrawMonitorID vm_death_lock; 66 static jboolean vm_death_active; 67 68 /* Given a jvmtiEnv*, return the C++ Agent class instance */ 69 static Agent * 70 get_agent(jvmtiEnv *jvmti) 71 { 72 jvmtiError err; 73 Agent *agent; 74 75 agent = NULL; 76 err = jvmti->GetEnvironmentLocalStorage((void**)&agent); 77 check_jvmti_error(jvmti, err, "get env local storage"); 78 if ( agent == NULL ) { 79 /* This should never happen, but we should check */ 80 fatal_error("ERROR: GetEnvironmentLocalStorage() returned NULL"); 81 } 82 return agent; 83 } 84 85 /* Enter raw monitor */ 86 static void 87 menter(jvmtiEnv *jvmti, jrawMonitorID rmon) 88 { 89 jvmtiError err; 90 91 err = jvmti->RawMonitorEnter(rmon); 92 check_jvmti_error(jvmti, err, "raw monitor enter"); 93 } 94 95 /* Exit raw monitor */ 96 static void 97 mexit(jvmtiEnv *jvmti, jrawMonitorID rmon) 98 { 99 jvmtiError err; 100 101 err = jvmti->RawMonitorExit(rmon); 102 check_jvmti_error(jvmti, err, "raw monitor exit"); 103 } 104 105 106 /* All callbacks need to be extern "C" */ 107 extern "C" { 108 static void JNICALL 109 vm_init(jvmtiEnv *jvmti, JNIEnv *env, jthread thread) 110 { 111 jvmtiError err; 112 Agent *agent; 113 114 /* Create raw monitor to protect against threads running after death */ 115 err = jvmti->CreateRawMonitor("Waiters vm_death lock", &vm_death_lock); 116 check_jvmti_error(jvmti, err, "create raw monitor"); 117 vm_death_active = JNI_FALSE; 118 119 /* Create an Agent instance, set JVMTI Local Storage */ 120 agent = new Agent(jvmti, env, thread); 121 err = jvmti->SetEnvironmentLocalStorage((const void*)agent); 122 check_jvmti_error(jvmti, err, "set env local storage"); 123 124 /* Enable all other events we want */ 125 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, 126 JVMTI_EVENT_VM_DEATH, NULL); 127 check_jvmti_error(jvmti, err, "set event notify"); 128 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, 129 JVMTI_EVENT_THREAD_START, NULL); 130 check_jvmti_error(jvmti, err, "set event notify"); 131 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, 132 JVMTI_EVENT_THREAD_END, NULL); 133 check_jvmti_error(jvmti, err, "set event notify"); 134 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, 135 JVMTI_EVENT_MONITOR_CONTENDED_ENTER, NULL); 136 check_jvmti_error(jvmti, err, "set event notify"); 137 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, 138 JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, NULL); 139 check_jvmti_error(jvmti, err, "set event notify"); 140 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, 141 JVMTI_EVENT_MONITOR_WAIT, NULL); 142 check_jvmti_error(jvmti, err, "set event notify"); 143 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, 144 JVMTI_EVENT_MONITOR_WAITED, NULL); 145 check_jvmti_error(jvmti, err, "set event notify"); 146 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, 147 JVMTI_EVENT_OBJECT_FREE, NULL); 148 check_jvmti_error(jvmti, err, "set event notify"); 149 } 150 static void JNICALL 151 vm_death(jvmtiEnv *jvmti, JNIEnv *env) 152 { 153 jvmtiError err; 154 Agent *agent; 155 156 /* Block all callbacks */ 157 menter(jvmti, vm_death_lock); { 158 /* Set flag for other callbacks */ 159 vm_death_active = JNI_TRUE; 160 161 /* Inform Agent instance of VM_DEATH */ 162 agent = get_agent(jvmti); 163 agent->vm_death(jvmti, env); 164 165 /* Reclaim space of Agent */ 166 err = jvmti->SetEnvironmentLocalStorage((const void*)NULL); 167 check_jvmti_error(jvmti, err, "set env local storage"); 168 delete agent; 169 } mexit(jvmti, vm_death_lock); 170 171 } 172 static void JNICALL 173 thread_start(jvmtiEnv *jvmti, JNIEnv *env, jthread thread) 174 { 175 menter(jvmti, vm_death_lock); { 176 if ( !vm_death_active ) { 177 get_agent(jvmti)->thread_start(jvmti, env, thread); 178 } 179 } mexit(jvmti, vm_death_lock); 180 } 181 static void JNICALL 182 thread_end(jvmtiEnv *jvmti, JNIEnv *env, jthread thread) 183 { 184 menter(jvmti, vm_death_lock); { 185 if ( !vm_death_active ) { 186 get_agent(jvmti)->thread_end(jvmti, env, thread); 187 } 188 } mexit(jvmti, vm_death_lock); 189 } 190 static void JNICALL 191 monitor_contended_enter(jvmtiEnv* jvmti, JNIEnv *env, 192 jthread thread, jobject object) 193 { 194 menter(jvmti, vm_death_lock); { 195 if ( !vm_death_active ) { 196 get_agent(jvmti)->monitor_contended_enter(jvmti, env, 197 thread, object); 198 } 199 } mexit(jvmti, vm_death_lock); 200 } 201 static void JNICALL 202 monitor_contended_entered(jvmtiEnv* jvmti, JNIEnv *env, 203 jthread thread, jobject object) 204 { 205 menter(jvmti, vm_death_lock); { 206 if ( !vm_death_active ) { 207 get_agent(jvmti)->monitor_contended_entered(jvmti, env, 208 thread, object); 209 } 210 } mexit(jvmti, vm_death_lock); 211 } 212 static void JNICALL 213 monitor_wait(jvmtiEnv* jvmti, JNIEnv *env, 214 jthread thread, jobject object, jlong timeout) 215 { 216 menter(jvmti, vm_death_lock); { 217 if ( !vm_death_active ) { 218 get_agent(jvmti)->monitor_wait(jvmti, env, thread, 219 object, timeout); 220 } 221 } mexit(jvmti, vm_death_lock); 222 } 223 static void JNICALL 224 monitor_waited(jvmtiEnv* jvmti, JNIEnv *env, 225 jthread thread, jobject object, jboolean timed_out) 226 { 227 menter(jvmti, vm_death_lock); { 228 if ( !vm_death_active ) { 229 get_agent(jvmti)->monitor_waited(jvmti, env, thread, 230 object, timed_out); 231 } 232 } mexit(jvmti, vm_death_lock); 233 } 234 static void JNICALL 235 object_free(jvmtiEnv* jvmti, jlong tag) 236 { 237 menter(jvmti, vm_death_lock); { 238 if ( !vm_death_active ) { 239 get_agent(jvmti)->object_free(jvmti, tag); 240 } 241 } mexit(jvmti, vm_death_lock); 242 } 243 244 /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ 245 JNIEXPORT jint JNICALL 246 DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) 247 { 248 jvmtiEnv *jvmti; 249 jint rc; 250 jvmtiError err; 251 jvmtiCapabilities capabilities; 252 jvmtiEventCallbacks callbacks; 253 254 /* Get JVMTI environment */ 255 rc = vm->GetEnv((void **)&jvmti, JVMTI_VERSION); 256 if (rc != JNI_OK) { 257 fatal_error("ERROR: Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc); 258 return -1; 259 } 260 261 /* Get/Add JVMTI capabilities */ 262 (void)memset(&capabilities, 0, sizeof(capabilities)); 263 capabilities.can_generate_monitor_events = 1; 264 capabilities.can_get_monitor_info = 1; 265 capabilities.can_tag_objects = 1; 266 capabilities.can_generate_object_free_events = 1; 267 err = jvmti->AddCapabilities(&capabilities); 268 check_jvmti_error(jvmti, err, "add capabilities"); 269 270 /* Set all callbacks and enable VM_INIT event notification */ 271 memset(&callbacks, 0, sizeof(callbacks)); 272 callbacks.VMInit = &vm_init; 273 callbacks.VMDeath = &vm_death; 274 callbacks.ThreadStart = &thread_start; 275 callbacks.ThreadEnd = &thread_end; 276 callbacks.MonitorContendedEnter = &monitor_contended_enter; 277 callbacks.MonitorContendedEntered = &monitor_contended_entered; 278 callbacks.MonitorWait = &monitor_wait; 279 callbacks.MonitorWaited = &monitor_waited; 280 callbacks.ObjectFree = &object_free; 281 err = jvmti->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks)); 282 check_jvmti_error(jvmti, err, "set event callbacks"); 283 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, 284 JVMTI_EVENT_VM_INIT, NULL); 285 check_jvmti_error(jvmti, err, "set event notify"); 286 return 0; 287 } 288 289 /* Agent_OnUnload() is called last */ 290 JNIEXPORT void JNICALL 291 DEF_Agent_OnUnload(JavaVM *vm) 292 { 293 } 294 295 } /* of extern "C" */