1 /*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <pthread.h>
18
19 #include <cstdio>
20 #include <iostream>
21 #include <vector>
22
23 #include "android-base/logging.h"
24 #include "jni.h"
25 #include "jvmti.h"
26
27 #include "scoped_local_ref.h"
28 #include "scoped_primitive_array.h"
29
30 // Test infrastructure
31 #include "jvmti_helper.h"
32 #include "test_env.h"
33
34 namespace art {
35 namespace Test1922OwnedMonitors {
36
doMonitorEnter(JNIEnv * env,jobject target)37 static bool doMonitorEnter(JNIEnv* env, jobject target) {
38 return env->MonitorEnter(target) != 0;
39 }
doMonitorExit(JNIEnv * env,jobject target)40 static bool doMonitorExit(JNIEnv* env, jobject target) {
41 return env->MonitorExit(target) != 0;
42 }
43
doCallRunnable(JNIEnv * env,jobject next)44 static bool doCallRunnable(JNIEnv* env, jobject next) {
45 ScopedLocalRef<jclass> run_class(env, env->FindClass("java/lang/Runnable"));
46 if (run_class.get() == nullptr) {
47 return true;
48 }
49 jmethodID run = env->GetMethodID(run_class.get(), "run", "()V");
50 if (env->ExceptionCheck()) {
51 return true;
52 }
53 env->CallVoidMethod(next, run);
54 return env->ExceptionCheck();
55 }
56
Java_art_Test1922_00024Target_lockThisNative(JNIEnv * env,jobject thiz,jobject next)57 extern "C" JNIEXPORT void JNICALL Java_art_Test1922_00024Target_lockThisNative(
58 JNIEnv* env, jobject thiz, jobject next) {
59 if (doMonitorEnter(env, thiz)) {
60 return;
61 }
62 if (doCallRunnable(env, next)) {
63 return;
64 }
65 if (doMonitorExit(env, thiz)) {
66 return;
67 }
68 }
69
Java_art_Test1922_00024Target_lockNative(JNIEnv * env,jobject thiz ATTRIBUTE_UNUSED,jobject mon,jobject next)70 extern "C" JNIEXPORT void JNICALL Java_art_Test1922_00024Target_lockNative(
71 JNIEnv* env, jobject thiz ATTRIBUTE_UNUSED, jobject mon, jobject next) {
72 if (doMonitorEnter(env, mon)) {
73 return;
74 }
75 if (doCallRunnable(env, next)) {
76 return;
77 }
78 if (doMonitorExit(env, mon)) {
79 return;
80 }
81 }
82
Java_art_Test1922_setupTest(JNIEnv * env,jclass)83 extern "C" JNIEXPORT void JNICALL Java_art_Test1922_setupTest(JNIEnv* env, jclass) {
84 jvmtiCapabilities caps;
85 memset(&caps, 0, sizeof(caps));
86 caps.can_get_owned_monitor_info = 1;
87 caps.can_get_owned_monitor_stack_depth_info = 1;
88 JvmtiErrorToException(env, jvmti_env, jvmti_env->AddCapabilities(&caps));
89 }
90
Java_art_Test1922_getOwnedMonitorStackDepthInfo(JNIEnv * env,jclass,jthread thread)91 extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test1922_getOwnedMonitorStackDepthInfo(
92 JNIEnv* env, jclass, jthread thread) {
93 jint len = 0;
94 jvmtiMonitorStackDepthInfo* monitors = nullptr;
95 if (JvmtiErrorToException(
96 env, jvmti_env, jvmti_env->GetOwnedMonitorStackDepthInfo(thread, &len, &monitors))) {
97 return nullptr;
98 }
99 ScopedLocalRef<jclass> ret_class(env, env->FindClass("art/Test1922$MonitorStackDepthInfo"));
100 if (ret_class.get() == nullptr) {
101 // CNFE should be pending.
102 return nullptr;
103 }
104 jmethodID constructor = env->GetMethodID(ret_class.get(), "<init>", "(ILjava/lang/Object;)V");
105 if (env->ExceptionCheck()) {
106 return nullptr;
107 }
108 return CreateObjectArray(env, len, "art/Test1922$MonitorStackDepthInfo",
109 [&](jint i) {
110 return env->NewObject(ret_class.get(),
111 constructor,
112 monitors[i].stack_depth,
113 monitors[i].monitor);
114 });
115 }
116
Java_art_Test1922_getOwnedMonitors(JNIEnv * env,jclass,jthread thread)117 extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test1922_getOwnedMonitors(JNIEnv* env,
118 jclass,
119 jthread thread) {
120 jint len = 0;
121 jobject* arr = nullptr;
122 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetOwnedMonitorInfo(thread, &len, &arr))) {
123 return nullptr;
124 }
125 ScopedLocalRef<jclass> obj_class(env, env->FindClass("java/lang/Object"));
126 if (obj_class.get() == nullptr) {
127 // CNFE should be pending.
128 return nullptr;
129 }
130 jobjectArray ret = env->NewObjectArray(len, obj_class.get(), nullptr);
131 if (ret == nullptr) {
132 return nullptr;
133 }
134 for (jint i = 0; i < len; i++) {
135 env->SetObjectArrayElement(ret, i, arr[i]);
136 if (env->ExceptionCheck()) {
137 return nullptr;
138 }
139 }
140 return ret;
141 }
142
143 } // namespace Test1922OwnedMonitors
144 } // namespace art
145