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 }