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 jint status = PASSED; 51 52 static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved); 53 54 JNIEXPORT void JNICALL 55 MonitorContendedEnter(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jobject monitor) { 56 jvmtiThreadInfo threadInfo; 57 jint monitorCount; 58 jobject *ownedMonitors; 59 60 (*jvmti)->GetThreadInfo(jvmti, thread, &threadInfo); 61 (*jvmti)->GetOwnedMonitorInfo(jvmti, thread, &monitorCount, &ownedMonitors); 62 63 printf("MonitorContendedEnter: %s owns %d monitor(s)\n", 64 threadInfo.name, monitorCount); 65 66 (*jvmti)->Deallocate(jvmti, (unsigned char *)ownedMonitors); 67 (*jvmti)->Deallocate(jvmti, (unsigned char *)threadInfo.name); 68 69 if (monitorCount != 0) { 70 status = FAILED; 71 } 72 } 73 74 JNIEXPORT void JNICALL 75 MonitorContendedEntered(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jobject monitor) { 76 jvmtiThreadInfo threadInfo; 77 jint monitorCount; 78 jobject *ownedMonitors; 79 80 (*jvmti)->GetThreadInfo(jvmti, thread, &threadInfo); 81 (*jvmti)->GetOwnedMonitorInfo(jvmti, thread, &monitorCount, &ownedMonitors); 82 83 printf("MonitorContendedEntered: %s owns %d monitor(s)\n", 84 threadInfo.name, monitorCount); 85 86 (*jvmti)->Deallocate(jvmti, (unsigned char *)ownedMonitors); 87 (*jvmti)->Deallocate(jvmti, (unsigned char *)threadInfo.name); 88 89 if (monitorCount != 1) { 90 status = FAILED; 91 } 92 } 93 94 JNIEXPORT jint JNICALL 95 Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { 96 return Agent_Initialize(jvm, options, reserved); 97 } 98 99 JNIEXPORT jint JNICALL 100 Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) { 101 return Agent_Initialize(jvm, options, reserved); 102 } 103 104 JNIEXPORT jint JNICALL 105 JNI_OnLoad(JavaVM *jvm, void *reserved) { 106 return JNI_VERSION_1_8; 107 } 108 109 static 110 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 111 jint res; 112 jvmtiError err; 113 jvmtiEnv *jvmti; 114 jvmtiCapabilities caps; 115 jvmtiEventCallbacks callbacks; 116 117 printf("Agent_OnLoad started\n"); 118 119 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), 120 JVMTI_VERSION_1); 121 if (res != JNI_OK || jvmti == NULL) { 122 printf(" Error: wrong result of a valid call to GetEnv!\n"); 123 return JNI_ERR; 124 } 125 126 err = (*jvmti)->GetPotentialCapabilities(jvmti, &caps); 127 if (err != JVMTI_ERROR_NONE) { 128 printf("Agent_OnLoad: error in JVMTI GetPotentialCapabilities: %d\n", err); 129 return JNI_ERR; 130 } 131 132 err = (*jvmti)->AddCapabilities(jvmti, &caps); 133 if (err != JVMTI_ERROR_NONE) { 134 printf("Agent_OnLoad: error in JVMTI AddCapabilities: %d\n", err); 135 } 136 137 err = (*jvmti)->GetCapabilities(jvmti, &caps); 138 if (err != JVMTI_ERROR_NONE) { 139 printf("Agent_OnLoad: error in JVMTI GetCapabilities: %d\n", err); 140 return JNI_ERR; 141 } 142 143 if (!caps.can_generate_monitor_events) { 144 printf("Warning: Monitor events are not implemented\n"); 145 } 146 if (!caps.can_get_owned_monitor_info) { 147 printf("Warning: GetOwnedMonitorInfo is not implemented\n"); 148 } 149 150 callbacks.MonitorContendedEnter = &MonitorContendedEnter; 151 callbacks.MonitorContendedEntered = &MonitorContendedEntered; 152 153 err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(jvmtiEventCallbacks)); 154 if (err != JVMTI_ERROR_NONE) { 155 printf("Agent_OnLoad: error in JVMTI SetEventCallbacks: %d\n", err); 156 } 157 158 err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, 159 JVMTI_EVENT_MONITOR_CONTENDED_ENTER, NULL); 160 if (err != JVMTI_ERROR_NONE) { 161 printf("Agent_OnLoad: error in JVMTI SetEventNotificationMode #1: %d\n", err); 162 } 163 err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, 164 JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, NULL); 165 if (err != JVMTI_ERROR_NONE) { 166 printf("Agent_OnLoad: error in JVMTI SetEventNotificationMode #2: %d\n", err); 167 } 168 printf("Agent_OnLoad finished\n"); 169 return JNI_OK; 170 } 171 172 JNIEXPORT jint JNICALL 173 Java_GetOwnedMonitorInfoTest_check(JNIEnv *env, jclass cls) { 174 return status; 175 } 176 177 #ifdef __cplusplus 178 } 179 #endif