1 /* 2 * Copyright (c) 2017, 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 24 #include <stdio.h> 25 #include <string.h> 26 #include "jvmti.h" 27 #include "jni.h" 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 #ifndef JNI_ENV_ARG 34 35 #ifdef __cplusplus 36 #define JNI_ENV_ARG(x, y) y 37 #define JNI_ENV_PTR(x) x 38 #else 39 #define JNI_ENV_ARG(x,y) x, y 40 #define JNI_ENV_PTR(x) (*x) 41 #endif 42 43 #endif 44 45 #define TranslateError(err) "JVMTI error" 46 47 #define PASSED 0 48 #define FAILED 2 49 50 static volatile jboolean event_has_posted = JNI_FALSE; 51 static volatile jint status = PASSED; 52 53 static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved); 54 55 JNIEXPORT void JNICALL 56 MonitorContendedEnter(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jobject monitor) { 57 jvmtiError err; 58 jvmtiThreadInfo threadInfo; 59 jint monitorCount; 60 jobject *ownedMonitors; 61 62 err = (*jvmti)->GetThreadInfo(jvmti, thread, &threadInfo); 63 if (err != JVMTI_ERROR_NONE) { 64 fprintf(stderr, "MonitorContendedEnter: error in JVMTI GetThreadInfo: %d\n", err); 65 status = FAILED; 66 event_has_posted = JNI_TRUE; 67 return; 68 } 69 err = (*jvmti)->GetOwnedMonitorInfo(jvmti, thread, &monitorCount, &ownedMonitors); 70 if (err != JVMTI_ERROR_NONE) { 71 fprintf(stderr, "MonitorContendedEnter: error in JVMTI GetOwnedMonitorInfo: %d\n", err); 72 status = FAILED; 73 event_has_posted = JNI_TRUE; 74 return; 75 } 76 77 printf("MonitorContendedEnter: %s owns %d monitor(s)\n", 78 threadInfo.name, monitorCount); 79 80 (*jvmti)->Deallocate(jvmti, (unsigned char *)ownedMonitors); 81 (*jvmti)->Deallocate(jvmti, (unsigned char *)threadInfo.name); 82 83 if (monitorCount != 0) { 84 fprintf(stderr, "MonitorContendedEnter: FAIL: monitorCount should be zero.\n"); 85 status = FAILED; 86 } 87 88 event_has_posted = JNI_TRUE; 89 } 90 91 JNIEXPORT void JNICALL 92 MonitorContendedEntered(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jobject monitor) { 93 jvmtiError err; 94 jvmtiThreadInfo threadInfo; 95 jint monitorCount; 96 jobject *ownedMonitors; 97 98 err = (*jvmti)->GetThreadInfo(jvmti, thread, &threadInfo); 99 if (err != JVMTI_ERROR_NONE) { 100 fprintf(stderr, "MonitorContendedEntered: error in JVMTI GetThreadInfo: %d\n", err); 101 status = FAILED; 102 return; 103 } 104 err = (*jvmti)->GetOwnedMonitorInfo(jvmti, thread, &monitorCount, &ownedMonitors); 105 if (err != JVMTI_ERROR_NONE) { 106 fprintf(stderr, "MonitorContendedEntered: error in JVMTI GetOwnedMonitorInfo: %d\n", err); 107 status = FAILED; 108 return; 109 } 110 111 printf("MonitorContendedEntered: %s owns %d monitor(s)\n", 112 threadInfo.name, monitorCount); 113 114 (*jvmti)->Deallocate(jvmti, (unsigned char *)ownedMonitors); 115 (*jvmti)->Deallocate(jvmti, (unsigned char *)threadInfo.name); 116 117 if (monitorCount != 1) { 118 fprintf(stderr, "MonitorContendedEnter: FAIL: monitorCount should be one.\n"); 119 status = FAILED; 120 } 121 } 122 123 JNIEXPORT jint JNICALL 124 Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { 125 return Agent_Initialize(jvm, options, reserved); 126 } 127 128 JNIEXPORT jint JNICALL 129 Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) { 130 return Agent_Initialize(jvm, options, reserved); 131 } 132 133 JNIEXPORT jint JNICALL 134 JNI_OnLoad(JavaVM *jvm, void *reserved) { 135 return JNI_VERSION_1_8; 136 } 137 138 static 139 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 140 jint res; 141 jvmtiError err; 142 jvmtiEnv *jvmti; 143 jvmtiCapabilities caps; 144 jvmtiEventCallbacks callbacks; 145 146 printf("Agent_OnLoad started\n"); 147 148 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), 149 JVMTI_VERSION_1); 150 if (res != JNI_OK || jvmti == NULL) { 151 fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n"); 152 return JNI_ERR; 153 } 154 155 err = (*jvmti)->GetPotentialCapabilities(jvmti, &caps); 156 if (err != JVMTI_ERROR_NONE) { 157 fprintf(stderr, "Agent_OnLoad: error in JVMTI GetPotentialCapabilities: %d\n", err); 158 return JNI_ERR; 159 } 160 161 err = (*jvmti)->AddCapabilities(jvmti, &caps); 162 if (err != JVMTI_ERROR_NONE) { 163 fprintf(stderr, "Agent_OnLoad: error in JVMTI AddCapabilities: %d\n", err); 164 return JNI_ERR; 165 } 166 167 err = (*jvmti)->GetCapabilities(jvmti, &caps); 168 if (err != JVMTI_ERROR_NONE) { 169 fprintf(stderr, "Agent_OnLoad: error in JVMTI GetCapabilities: %d\n", err); 170 return JNI_ERR; 171 } 172 173 if (!caps.can_generate_monitor_events) { 174 fprintf(stderr, "Warning: Monitor events are not implemented\n"); 175 return JNI_ERR; 176 } 177 if (!caps.can_get_owned_monitor_info) { 178 fprintf(stderr, "Warning: GetOwnedMonitorInfo is not implemented\n"); 179 return JNI_ERR; 180 } 181 182 callbacks.MonitorContendedEnter = &MonitorContendedEnter; 183 callbacks.MonitorContendedEntered = &MonitorContendedEntered; 184 185 err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(jvmtiEventCallbacks)); 186 if (err != JVMTI_ERROR_NONE) { 187 fprintf(stderr, "Agent_OnLoad: error in JVMTI SetEventCallbacks: %d\n", err); 188 return JNI_ERR; 189 } 190 191 err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, 192 JVMTI_EVENT_MONITOR_CONTENDED_ENTER, NULL); 193 if (err != JVMTI_ERROR_NONE) { 194 fprintf(stderr, "Agent_OnLoad: error in JVMTI SetEventNotificationMode #1: %d\n", err); 195 return JNI_ERR; 196 } 197 err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, 198 JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, NULL); 199 if (err != JVMTI_ERROR_NONE) { 200 fprintf(stderr, "Agent_OnLoad: error in JVMTI SetEventNotificationMode #2: %d\n", err); 201 return JNI_ERR; 202 } 203 printf("Agent_OnLoad finished\n"); 204 return JNI_OK; 205 } 206 207 JNIEXPORT jint JNICALL 208 Java_GetOwnedMonitorInfoTest_check(JNIEnv *env, jclass cls) { 209 return status; 210 } 211 212 JNIEXPORT jboolean JNICALL 213 Java_GetOwnedMonitorInfoTest_hasEventPosted(JNIEnv *env, jclass cls) { 214 return event_has_posted; 215 } 216 217 #ifdef __cplusplus 218 } 219 #endif