1 /*
2 * Copyright (C) 2017 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 "jni.h"
18
19 #include "android-base/logging.h"
20 #include "android-base/macros.h"
21 #include "jni_helper.h"
22 #include "jvmti_helper.h"
23 #include "jvmti.h"
24 #include "scoped_primitive_array.h"
25 #include "test_env.h"
26
27 namespace art {
28
Java_android_jvmti_cts_JniBindings_setTag(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED,jobject obj,jlong tag)29 extern "C" JNIEXPORT void JNICALL Java_android_jvmti_cts_JniBindings_setTag(
30 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject obj, jlong tag) {
31 jvmtiError ret = jvmti_env->SetTag(obj, tag);
32 JvmtiErrorToException(env, jvmti_env, ret);
33 }
34
Java_android_jvmti_cts_JniBindings_getTag(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED,jobject obj)35 extern "C" JNIEXPORT jlong JNICALL Java_android_jvmti_cts_JniBindings_getTag(
36 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject obj) {
37 jlong tag = 0;
38 jvmtiError ret = jvmti_env->GetTag(obj, &tag);
39 if (JvmtiErrorToException(env, jvmti_env, ret)) {
40 return 0;
41 }
42 return tag;
43 }
44
Java_android_jvmti_cts_JvmtiTaggingTest_getTaggedObjects(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED,jlongArray searchTags,jboolean returnObjects,jboolean returnTags)45 extern "C" JNIEXPORT jobjectArray JNICALL Java_android_jvmti_cts_JvmtiTaggingTest_getTaggedObjects(
46 JNIEnv* env,
47 jclass klass ATTRIBUTE_UNUSED,
48 jlongArray searchTags,
49 jboolean returnObjects,
50 jboolean returnTags) {
51 ScopedLongArrayRO scoped_array(env);
52 if (searchTags != nullptr) {
53 scoped_array.reset(searchTags);
54 }
55 const jlong* tag_ptr = scoped_array.get();
56 if (tag_ptr == nullptr) {
57 // Can never pass null.
58 tag_ptr = reinterpret_cast<const jlong*>(1);
59 }
60
61 jint result_count = -1;
62 jobject* result_object_array = nullptr;
63 jobject** result_object_array_ptr = returnObjects == JNI_TRUE ? &result_object_array : nullptr;
64 jlong* result_tag_array = nullptr;
65 jlong** result_tag_array_ptr = returnTags == JNI_TRUE ? &result_tag_array : nullptr;
66
67 jvmtiError ret = jvmti_env->GetObjectsWithTags(scoped_array.size(),
68 tag_ptr,
69 &result_count,
70 result_object_array_ptr,
71 result_tag_array_ptr);
72 if (JvmtiErrorToException(env, jvmti_env, ret)) {
73 return nullptr;
74 }
75
76 CHECK_GE(result_count, 0);
77
78 jobjectArray resultObjectArray = nullptr;
79 if (returnObjects == JNI_TRUE) {
80 auto callback = [&](jint i) {
81 return result_object_array[i];
82 };
83 resultObjectArray = CreateObjectArray(env, result_count, "java/lang/Object", callback);
84 if (resultObjectArray == nullptr) {
85 return nullptr;
86 }
87 }
88 if (result_object_array != nullptr) {
89 CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, result_object_array));
90 }
91
92 jlongArray resultTagArray = nullptr;
93 if (returnTags == JNI_TRUE) {
94 resultTagArray = env->NewLongArray(result_count);
95 if (resultTagArray == nullptr) {
96 return nullptr;
97 }
98 env->SetLongArrayRegion(resultTagArray, 0, result_count, result_tag_array);
99 }
100 if (result_tag_array != nullptr) {
101 CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, result_tag_array));
102 }
103
104 jobject count_integer;
105 {
106 ScopedLocalRef<jclass> integer_class(env, env->FindClass("java/lang/Integer"));
107 jmethodID methodID = env->GetMethodID(integer_class.get(), "<init>", "(I)V");
108 count_integer = env->NewObject(integer_class.get(), methodID, result_count);
109 if (count_integer == nullptr) {
110 return nullptr;
111 }
112 }
113
114 auto callback = [&](jint i) -> jobject {
115 switch(i) {
116 case 0:
117 return resultObjectArray;
118 case 1:
119 return resultTagArray;
120 case 2:
121 return count_integer;
122 default:
123 LOG(FATAL) << "Unexpected";
124 return nullptr;
125 }
126 };
127 return CreateObjectArray(env, 3, "java/lang/Object", callback);
128 }
129
130 } // namespace art
131
132