Home | History | Annotate | Download | only in 1922-owned-monitors-info
      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 
     37 static bool doMonitorEnter(JNIEnv* env, jobject target) {
     38   return env->MonitorEnter(target) != 0;
     39 }
     40 static bool doMonitorExit(JNIEnv* env, jobject target) {
     41   return env->MonitorExit(target) != 0;
     42 }
     43 
     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 
     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 
     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 
     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 
     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 
    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