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_binder.h"
22 #include "jni_helper.h"
23 #include "jvmti_helper.h"
24 #include "jvmti.h"
25 #include "scoped_primitive_array.h"
26 #include "test_env.h"
27
28 namespace art {
29
Java_android_jvmti_cts_JniBindings_setTag(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED,jobject obj,jlong tag)30 extern "C" JNIEXPORT void JNICALL Java_android_jvmti_cts_JniBindings_setTag(
31 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject obj, jlong tag) {
32 jvmtiError ret = jvmti_env->SetTag(obj, tag);
33 JvmtiErrorToException(env, jvmti_env, ret);
34 }
35
Java_android_jvmti_cts_JniBindings_getTag(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED,jobject obj)36 extern "C" JNIEXPORT jlong JNICALL Java_android_jvmti_cts_JniBindings_getTag(
37 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject obj) {
38 jlong tag = 0;
39 jvmtiError ret = jvmti_env->GetTag(obj, &tag);
40 if (JvmtiErrorToException(env, jvmti_env, ret)) {
41 return 0;
42 }
43 return tag;
44 }
45
Java_android_jvmti_cts_JvmtiTaggingTest_getTaggedObjects(JNIEnv * env,jclass klass ATTRIBUTE_UNUSED,jlongArray searchTags,jboolean returnObjects,jboolean returnTags)46 extern "C" JNIEXPORT jobjectArray JNICALL Java_android_jvmti_cts_JvmtiTaggingTest_getTaggedObjects(
47 JNIEnv* env,
48 jclass klass ATTRIBUTE_UNUSED,
49 jlongArray searchTags,
50 jboolean returnObjects,
51 jboolean returnTags) {
52 ScopedLongArrayRO scoped_array(env);
53 if (searchTags != nullptr) {
54 scoped_array.reset(searchTags);
55 }
56 const jlong* tag_ptr = scoped_array.get();
57 if (tag_ptr == nullptr) {
58 // Can never pass null.
59 tag_ptr = reinterpret_cast<const jlong*>(1);
60 }
61
62 jint result_count = -1;
63 jobject* result_object_array = nullptr;
64 jobject** result_object_array_ptr = returnObjects == JNI_TRUE ? &result_object_array : nullptr;
65 jlong* result_tag_array = nullptr;
66 jlong** result_tag_array_ptr = returnTags == JNI_TRUE ? &result_tag_array : nullptr;
67
68 jvmtiError ret = jvmti_env->GetObjectsWithTags(scoped_array.size(),
69 tag_ptr,
70 &result_count,
71 result_object_array_ptr,
72 result_tag_array_ptr);
73 if (JvmtiErrorToException(env, jvmti_env, ret)) {
74 return nullptr;
75 }
76
77 CHECK_GE(result_count, 0);
78
79 jobjectArray resultObjectArray = nullptr;
80 if (returnObjects == JNI_TRUE) {
81 auto callback = [&](jint i) {
82 return result_object_array[i];
83 };
84 resultObjectArray = CreateObjectArray(env, result_count, "java/lang/Object", callback);
85 if (resultObjectArray == nullptr) {
86 return nullptr;
87 }
88 }
89 if (result_object_array != nullptr) {
90 CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, result_object_array));
91 }
92
93 jlongArray resultTagArray = nullptr;
94 if (returnTags == JNI_TRUE) {
95 resultTagArray = env->NewLongArray(result_count);
96 if (resultTagArray == nullptr) {
97 return nullptr;
98 }
99 env->SetLongArrayRegion(resultTagArray, 0, result_count, result_tag_array);
100 }
101 if (result_tag_array != nullptr) {
102 CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, result_tag_array));
103 }
104
105 jobject count_integer;
106 {
107 ScopedLocalRef<jclass> integer_class(env, env->FindClass("java/lang/Integer"));
108 jmethodID methodID = env->GetMethodID(integer_class.get(), "<init>", "(I)V");
109 count_integer = env->NewObject(integer_class.get(), methodID, result_count);
110 if (count_integer == nullptr) {
111 return nullptr;
112 }
113 }
114
115 auto callback = [&](jint i) -> jobject {
116 jobject ret = nullptr;
117 switch(i) {
118 case 0:
119 ret = resultObjectArray;
120 break;
121 case 1:
122 ret = resultTagArray;
123 break;
124 case 2:
125 ret = count_integer;
126 break;
127 default:
128 LOG(FATAL) << "Unexpected";
129 }
130 return ret;
131 };
132 return CreateObjectArray(env, 3, "java/lang/Object", callback);
133 }
134
135 static JNINativeMethod gMethodsForMain[] = {
136 { "setTag", "(Ljava/lang/Object;J)V",
137 (void*)Java_android_jvmti_cts_JniBindings_setTag },
138
139 { "getTag", "(Ljava/lang/Object;)J",
140 (void*)Java_android_jvmti_cts_JniBindings_getTag },
141 };
142
register_art_Main(jvmtiEnv * jenv,JNIEnv * env)143 void register_art_Main(jvmtiEnv* jenv, JNIEnv* env) {
144 ScopedLocalRef<jclass> klass(env, GetClass(jenv, env, "art/Main", nullptr));
145 if (klass.get() == nullptr) {
146 env->ExceptionClear();
147 return;
148 }
149
150 env->RegisterNatives(klass.get(), gMethodsForMain,
151 sizeof(gMethodsForMain) / sizeof(JNINativeMethod));
152 if (env->ExceptionCheck()) {
153 env->ExceptionClear();
154 LOG(ERROR) << "Could not register natives for Main class";
155 }
156 }
157
158 static JNINativeMethod gMethods[] = {
159 { "getTaggedObjects", "([JZZ)[Ljava/lang/Object;",
160 (void*)Java_android_jvmti_cts_JvmtiTaggingTest_getTaggedObjects },
161 };
162
register_android_jvmti_cts_JvmtiTaggingTest(jvmtiEnv * jenv,JNIEnv * env)163 void register_android_jvmti_cts_JvmtiTaggingTest(jvmtiEnv* jenv, JNIEnv* env) {
164 ScopedLocalRef<jclass> klass(env, GetClass(jenv, env,
165 "android/jvmti/cts/JvmtiTaggingTest", nullptr));
166 if (klass.get() == nullptr) {
167 env->ExceptionClear();
168 return;
169 }
170
171 env->RegisterNatives(klass.get(), gMethods, sizeof(gMethods) / sizeof(JNINativeMethod));
172 if (env->ExceptionCheck()) {
173 env->ExceptionClear();
174 LOG(ERROR) << "Could not register natives for JvmtiTaggingTest class";
175 }
176 }
177
178 } // namespace art
179
180