blob: 66a83689a2e834ee5c7fb90f121390dd40a31a57 [file] [log] [blame]
Alex Light88e1ddd2017-08-21 13:09:55 -07001/*
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
34namespace art {
35namespace Test1922OwnedMonitors {
36
37static bool doMonitorEnter(JNIEnv* env, jobject target) {
38 return env->MonitorEnter(target) != 0;
39}
40static bool doMonitorExit(JNIEnv* env, jobject target) {
41 return env->MonitorExit(target) != 0;
42}
43
44static 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
57extern "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
70extern "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
83extern "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
91extern "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
117extern "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