Home | History | Annotate | Download | only in 903-hello-tagging
      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 #include "scoped_local_ref.h"
     27 #include "scoped_primitive_array.h"
     28 
     29 // Test infrastructure
     30 #include "jvmti_helper.h"
     31 #include "test_env.h"
     32 
     33 namespace art {
     34 namespace Test903HelloTagging {
     35 
     36 extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test903_getTaggedObjects(
     37     JNIEnv* env, jclass, jlongArray searchTags, jboolean returnObjects, jboolean returnTags) {
     38   ScopedLongArrayRO scoped_array(env);
     39   if (searchTags != nullptr) {
     40     scoped_array.reset(searchTags);
     41   }
     42   const jlong* tag_ptr = scoped_array.get();
     43   if (tag_ptr == nullptr) {
     44     // Can never pass null.
     45     tag_ptr = reinterpret_cast<const jlong*>(1);
     46   }
     47 
     48   jint result_count;
     49   jobject* result_object_array;
     50   jobject** result_object_array_ptr = returnObjects == JNI_TRUE ? &result_object_array : nullptr;
     51   jlong* result_tag_array;
     52   jlong** result_tag_array_ptr = returnTags == JNI_TRUE ? &result_tag_array : nullptr;
     53 
     54   jvmtiError ret = jvmti_env->GetObjectsWithTags(scoped_array.size(),
     55                                                  tag_ptr,
     56                                                  &result_count,
     57                                                  result_object_array_ptr,
     58                                                  result_tag_array_ptr);
     59   if (JvmtiErrorToException(env, jvmti_env, ret)) {
     60     return nullptr;
     61   }
     62 
     63   CHECK_GE(result_count, 0);
     64 
     65   ScopedLocalRef<jclass> obj_class(env, env->FindClass("java/lang/Object"));
     66   if (obj_class.get() == nullptr) {
     67     return nullptr;
     68   }
     69 
     70   jobjectArray resultObjectArray = nullptr;
     71   if (returnObjects == JNI_TRUE) {
     72     resultObjectArray = env->NewObjectArray(result_count, obj_class.get(), nullptr);
     73     if (resultObjectArray == nullptr) {
     74       return nullptr;
     75     }
     76     for (jint i = 0; i < result_count; ++i) {
     77       env->SetObjectArrayElement(resultObjectArray, i, result_object_array[i]);
     78     }
     79   }
     80 
     81   jlongArray resultTagArray = nullptr;
     82   if (returnTags == JNI_TRUE) {
     83     resultTagArray = env->NewLongArray(result_count);
     84     env->SetLongArrayRegion(resultTagArray, 0, result_count, result_tag_array);
     85   }
     86 
     87   jobject count_integer;
     88   {
     89     ScopedLocalRef<jclass> integer_class(env, env->FindClass("java/lang/Integer"));
     90     jmethodID methodID = env->GetMethodID(integer_class.get(), "<init>", "(I)V");
     91     count_integer = env->NewObject(integer_class.get(), methodID, result_count);
     92     if (count_integer == nullptr) {
     93       return nullptr;
     94     }
     95   }
     96 
     97   jobjectArray resultArray = env->NewObjectArray(3, obj_class.get(), nullptr);
     98   if (resultArray == nullptr) {
     99     return nullptr;
    100   }
    101   env->SetObjectArrayElement(resultArray, 0, resultObjectArray);
    102   env->SetObjectArrayElement(resultArray, 1, resultTagArray);
    103   env->SetObjectArrayElement(resultArray, 2, count_integer);
    104 
    105   return resultArray;
    106 }
    107 
    108 static jvmtiEnv* CreateJvmtiEnv(JNIEnv* env) {
    109   JavaVM* jvm;
    110   CHECK_EQ(0, env->GetJavaVM(&jvm));
    111 
    112   jvmtiEnv* new_jvmti_env;
    113   CHECK_EQ(0, jvm->GetEnv(reinterpret_cast<void**>(&new_jvmti_env), JVMTI_VERSION_1_0));
    114 
    115   jvmtiCapabilities capa;
    116   memset(&capa, 0, sizeof(jvmtiCapabilities));
    117   capa.can_tag_objects = 1;
    118   jvmtiError error = new_jvmti_env->AddCapabilities(&capa);
    119   CHECK_EQ(JVMTI_ERROR_NONE, error);
    120 
    121   return new_jvmti_env;
    122 }
    123 
    124 static void SetTag(jvmtiEnv* env, jobject obj, jlong tag) {
    125   jvmtiError ret = env->SetTag(obj, tag);
    126   CHECK_EQ(JVMTI_ERROR_NONE, ret);
    127 }
    128 
    129 static jlong GetTag(jvmtiEnv* env, jobject obj) {
    130   jlong tag;
    131   jvmtiError ret = env->GetTag(obj, &tag);
    132   CHECK_EQ(JVMTI_ERROR_NONE, ret);
    133   return tag;
    134 }
    135 
    136 extern "C" JNIEXPORT jlongArray JNICALL Java_art_Test903_testTagsInDifferentEnvs(
    137     JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject obj, jlong base_tag, jint count) {
    138   std::unique_ptr<jvmtiEnv*[]> envs = std::unique_ptr<jvmtiEnv*[]>(new jvmtiEnv*[count]);
    139   envs[0] = jvmti_env;
    140   for (int32_t i = 1; i != count; ++i) {
    141     envs[i] = CreateJvmtiEnv(env);
    142   }
    143 
    144   for (int32_t i = 0; i != count; ++i) {
    145     SetTag(envs[i], obj, base_tag + i);
    146   }
    147   std::unique_ptr<jlong[]> vals = std::unique_ptr<jlong[]>(new jlong[count]);
    148   for (int32_t i = 0; i != count; ++i) {
    149     vals[i] = GetTag(envs[i], obj);
    150   }
    151 
    152   for (int32_t i = 1; i != count; ++i) {
    153     CHECK_EQ(JVMTI_ERROR_NONE, envs[i]->DisposeEnvironment());
    154   }
    155 
    156   jlongArray res = env->NewLongArray(count);
    157   if (res == nullptr) {
    158     return nullptr;
    159   }
    160   env->SetLongArrayRegion(res, 0, count, vals.get());
    161   return res;
    162 }
    163 
    164 }  // namespace Test903HelloTagging
    165 }  // namespace art
    166