1 /* 2 * Copyright (c) 2020, 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 "agent_common.hpp" 28 #include "JVMTITools.hpp" 29 30 extern "C" { 31 32 33 #define PASSED 0 34 #define STATUS_FAILED 2 35 36 static jvmtiEnv *jvmti = NULL; 37 static jvmtiCapabilities caps; 38 static jint result = PASSED; 39 static jboolean printdump = JNI_FALSE; 40 41 #ifdef STATIC_BUILD 42 JNIEXPORT jint JNICALL Agent_OnLoad_objmonusage007(JavaVM *jvm, char *options, void *reserved) { 43 return Agent_Initialize(jvm, options, reserved); 44 } 45 JNIEXPORT jint JNICALL Agent_OnAttach_objmonusage007(JavaVM *jvm, char *options, void *reserved) { 46 return Agent_Initialize(jvm, options, reserved); 47 } 48 JNIEXPORT jint JNI_OnLoad_objmonusage007(JavaVM *jvm, char *options, void *reserved) { 49 return JNI_VERSION_1_8; 50 } 51 #endif 52 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 53 jint res; 54 jvmtiError err; 55 56 if (options != NULL && strcmp(options, "printdump") == 0) { 57 printdump = JNI_TRUE; 58 } 59 60 res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1); 61 if (res != JNI_OK || jvmti == NULL) { 62 printf("Wrong result of a valid call to GetEnv !\n"); 63 return JNI_ERR; 64 } 65 66 err = jvmti->GetPotentialCapabilities(&caps); 67 if (err != JVMTI_ERROR_NONE) { 68 printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n", 69 TranslateError(err), err); 70 return JNI_ERR; 71 } 72 73 err = jvmti->AddCapabilities(&caps); 74 if (err != JVMTI_ERROR_NONE) { 75 printf("(AddCapabilities) unexpected error: %s (%d)\n", 76 TranslateError(err), err); 77 return JNI_ERR; 78 } 79 80 err = jvmti->GetCapabilities(&caps); 81 if (err != JVMTI_ERROR_NONE) { 82 printf("(GetCapabilities) unexpected error: %s (%d)\n", 83 TranslateError(err), err); 84 return JNI_ERR; 85 } 86 87 if (!caps.can_get_monitor_info) { 88 printf("Warning: GetObjectMonitorUsage is not implemented\n"); 89 } 90 91 return JNI_OK; 92 } 93 94 JNIEXPORT void JNICALL 95 Java_nsk_jvmti_GetObjectMonitorUsage_objmonusage007_check(JNIEnv *env, 96 jclass cls, jobject obj, jthread owner, 97 jint entryCount, jint waiterCount) { 98 jvmtiError err; 99 jvmtiMonitorUsage inf; 100 jvmtiThreadInfo tinf; 101 int j; 102 103 if (result == STATUS_FAILED) { 104 return; 105 } 106 107 err = jvmti->GetObjectMonitorUsage(obj, &inf); 108 if (err == JVMTI_ERROR_MUST_POSSESS_CAPABILITY && 109 !caps.can_get_monitor_info) { 110 /* Ok, it's expected */ 111 return; 112 } else if (err != JVMTI_ERROR_NONE) { 113 printf("(GetMonitorInfo) unexpected error: %s (%d)\n", 114 TranslateError(err), err); 115 result = STATUS_FAILED; 116 return; 117 } 118 119 if (printdump == JNI_TRUE) { 120 if (inf.owner == NULL) { 121 printf(">>> owner: none (0x0)\n"); 122 } else { 123 jvmti->GetThreadInfo(inf.owner, &tinf); 124 printf(">>> owner: %s (0x%p)\n", 125 tinf.name, inf.owner); 126 } 127 printf(">>> entry_count: %d\n", inf.entry_count); 128 printf(">>> waiter_count: %d\n", inf.waiter_count); 129 if (inf.waiter_count > 0) { 130 printf(">>> waiters:\n"); 131 for (j = 0; j < inf.waiter_count; j++) { 132 jvmti->GetThreadInfo(inf.waiters[j], &tinf); 133 printf(">>> %2d: %s (0x%p)\n", 134 j, tinf.name, inf.waiters[j]); 135 } 136 } 137 printf(">>> notify_waiter_count: %d\n", inf.notify_waiter_count); 138 if (inf.notify_waiter_count > 0) { 139 printf(">>> notify_waiters:\n"); 140 for (j = 0; j < inf.notify_waiter_count; j++) { 141 jvmti->GetThreadInfo(inf.notify_waiters[j], &tinf); 142 printf(">>> %2d: %s (0x%p)\n", 143 j, tinf.name, inf.notify_waiters[j]); 144 } 145 } 146 } 147 148 if (!env->IsSameObject(owner, inf.owner)) { 149 jvmti->GetThreadInfo(inf.owner, &tinf); 150 printf(" unexpected owner: %s (0x%p)\n", tinf.name, inf.owner); 151 result = STATUS_FAILED; 152 } 153 154 if (inf.entry_count != entryCount) { 155 printf(" entry_count expected: %d, actually: %d\n", 156 entryCount, inf.entry_count); 157 result = STATUS_FAILED; 158 } 159 160 if (inf.waiter_count != waiterCount) { 161 printf(" waiter_count expected: %d, actually: %d\n", 162 waiterCount, inf.waiter_count); 163 result = STATUS_FAILED; 164 } 165 } 166 167 JNIEXPORT jint JNICALL 168 Java_nsk_jvmti_GetObjectMonitorUsage_objmonusage007_getResult(JNIEnv *env, jclass cls) { 169 return result; 170 } 171 172 }