1 /*
2 * Copyright (C) 2011 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_internal.h"
18
19 #include "android-base/stringprintf.h"
20
21 #include "art_method-inl.h"
22 #include "common_runtime_test.h"
23 #include "indirect_reference_table.h"
24 #include "java_vm_ext.h"
25 #include "jni_env_ext.h"
26 #include "mirror/string-inl.h"
27 #include "nativehelper/scoped_local_ref.h"
28 #include "scoped_thread_state_change-inl.h"
29
30 namespace art {
31
32 using android::base::StringPrintf;
33
34 class JniInternalTest : public CommonRuntimeTest {
35 protected:
SetUp()36 void SetUp() override {
37 CommonRuntimeTest::SetUp();
38
39 vm_ = Runtime::Current()->GetJavaVM();
40
41 // Turn on -verbose:jni for the JNI tests.
42 // gLogVerbosity.jni = true;
43
44 vm_->AttachCurrentThread(&env_, nullptr);
45
46 ScopedLocalRef<jclass> aioobe(env_,
47 env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
48 CHECK(aioobe.get() != nullptr);
49 aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
50
51 ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException"));
52 CHECK(ase.get() != nullptr);
53 ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get()));
54
55 ScopedLocalRef<jclass> sioobe(env_,
56 env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
57 CHECK(sioobe.get() != nullptr);
58 sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
59 }
60
ExpectException(jclass exception_class)61 void ExpectException(jclass exception_class) {
62 ScopedObjectAccess soa(env_);
63 EXPECT_TRUE(env_->ExceptionCheck())
64 << mirror::Class::PrettyDescriptor(soa.Decode<mirror::Class>(exception_class));
65 jthrowable exception = env_->ExceptionOccurred();
66 EXPECT_NE(nullptr, exception);
67 env_->ExceptionClear();
68 EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class));
69 }
70
CleanUpJniEnv()71 void CleanUpJniEnv() {
72 if (aioobe_ != nullptr) {
73 env_->DeleteGlobalRef(aioobe_);
74 aioobe_ = nullptr;
75 }
76 if (ase_ != nullptr) {
77 env_->DeleteGlobalRef(ase_);
78 ase_ = nullptr;
79 }
80 if (sioobe_ != nullptr) {
81 env_->DeleteGlobalRef(sioobe_);
82 sioobe_ = nullptr;
83 }
84 }
85
TearDown()86 void TearDown() override {
87 CleanUpJniEnv();
88 CommonRuntimeTest::TearDown();
89 }
90
GetPrimitiveClass(char descriptor)91 jclass GetPrimitiveClass(char descriptor) {
92 ScopedObjectAccess soa(env_);
93 ObjPtr<mirror::Class> c = class_linker_->FindPrimitiveClass(descriptor);
94 CHECK(c != nullptr);
95 return soa.AddLocalReference<jclass>(c);
96 }
97
ExpectClassFound(const char * name)98 void ExpectClassFound(const char* name) {
99 EXPECT_NE(env_->FindClass(name), nullptr) << name;
100 EXPECT_FALSE(env_->ExceptionCheck()) << name;
101 }
102
ExpectClassNotFound(const char * name,bool check_jni,const char * check_jni_msg,CheckJniAbortCatcher * abort_catcher)103 void ExpectClassNotFound(const char* name, bool check_jni, const char* check_jni_msg,
104 CheckJniAbortCatcher* abort_catcher) {
105 EXPECT_EQ(env_->FindClass(name), nullptr) << name;
106 if (!check_jni || check_jni_msg == nullptr) {
107 EXPECT_TRUE(env_->ExceptionCheck()) << name;
108 env_->ExceptionClear();
109 } else {
110 abort_catcher->Check(check_jni_msg);
111 }
112 }
113
FindClassTest(bool check_jni)114 void FindClassTest(bool check_jni) {
115 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
116 CheckJniAbortCatcher check_jni_abort_catcher;
117
118 // Null argument is always an abort.
119 env_->FindClass(nullptr);
120 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
121 : "name == null");
122
123 // Reference types...
124 ExpectClassFound("java/lang/String");
125 // ...for arrays too, where you must include "L;".
126 ExpectClassFound("[Ljava/lang/String;");
127 // Primitive arrays are okay too, if the primitive type is valid.
128 ExpectClassFound("[C");
129
130 // But primitive types aren't allowed...
131 ExpectClassNotFound("C", check_jni, nullptr, &check_jni_abort_catcher);
132 ExpectClassNotFound("V", check_jni, nullptr, &check_jni_abort_catcher);
133 ExpectClassNotFound("K", check_jni, nullptr, &check_jni_abort_catcher);
134
135 if (check_jni) {
136 // Check JNI will reject invalid class names as aborts but without pending exceptions.
137 EXPECT_EQ(env_->FindClass("java.lang.String"), nullptr);
138 EXPECT_FALSE(env_->ExceptionCheck());
139 check_jni_abort_catcher.Check("illegal class name 'java.lang.String'");
140
141 EXPECT_EQ(env_->FindClass("[Ljava.lang.String;"), nullptr);
142 EXPECT_FALSE(env_->ExceptionCheck());
143 check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'");
144 } else {
145 // Without check JNI we're tolerant and replace '.' with '/'.
146 ExpectClassFound("java.lang.String");
147 ExpectClassFound("[Ljava.lang.String;");
148 }
149
150 ExpectClassNotFound("Ljava.lang.String;", check_jni, "illegal class name 'Ljava.lang.String;'",
151 &check_jni_abort_catcher);
152 ExpectClassNotFound("[java.lang.String", check_jni, "illegal class name '[java.lang.String'",
153 &check_jni_abort_catcher);
154
155 // You can't include the "L;" in a JNI class descriptor.
156 ExpectClassNotFound("Ljava/lang/String;", check_jni, "illegal class name 'Ljava/lang/String;'",
157 &check_jni_abort_catcher);
158
159 // But you must include it for an array of any reference type.
160 ExpectClassNotFound("[java/lang/String", check_jni, "illegal class name '[java/lang/String'",
161 &check_jni_abort_catcher);
162
163 ExpectClassNotFound("[K", check_jni, "illegal class name '[K'", &check_jni_abort_catcher);
164
165 // Void arrays aren't allowed.
166 ExpectClassNotFound("[V", check_jni, "illegal class name '[V'", &check_jni_abort_catcher);
167
168 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
169 }
170
GetFieldIdBadArgumentTest(bool check_jni)171 void GetFieldIdBadArgumentTest(bool check_jni) {
172 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
173 CheckJniAbortCatcher check_jni_abort_catcher;
174
175 jclass c = env_->FindClass("java/lang/String");
176 ASSERT_NE(c, nullptr);
177
178 jfieldID fid = env_->GetFieldID(nullptr, "count", "I");
179 EXPECT_EQ(nullptr, fid);
180 check_jni_abort_catcher.Check(check_jni ? "GetFieldID received NULL jclass"
181 : "java_class == null");
182 fid = env_->GetFieldID(c, nullptr, "I");
183 EXPECT_EQ(nullptr, fid);
184 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
185 : "name == null");
186 fid = env_->GetFieldID(c, "count", nullptr);
187 EXPECT_EQ(nullptr, fid);
188 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
189 : "sig == null");
190
191 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
192 }
193
GetStaticFieldIdBadArgumentTest(bool check_jni)194 void GetStaticFieldIdBadArgumentTest(bool check_jni) {
195 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
196 CheckJniAbortCatcher check_jni_abort_catcher;
197
198 jclass c = env_->FindClass("java/lang/String");
199 ASSERT_NE(c, nullptr);
200
201 jfieldID fid = env_->GetStaticFieldID(nullptr, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
202 EXPECT_EQ(nullptr, fid);
203 check_jni_abort_catcher.Check(check_jni ? "GetStaticFieldID received NULL jclass"
204 : "java_class == null");
205 fid = env_->GetStaticFieldID(c, nullptr, "Ljava/util/Comparator;");
206 EXPECT_EQ(nullptr, fid);
207 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
208 : "name == null");
209 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", nullptr);
210 EXPECT_EQ(nullptr, fid);
211 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
212 : "sig == null");
213
214 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
215 }
216
GetMethodIdBadArgumentTest(bool check_jni)217 void GetMethodIdBadArgumentTest(bool check_jni) {
218 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
219 CheckJniAbortCatcher check_jni_abort_catcher;
220
221 jmethodID method = env_->GetMethodID(nullptr, "<init>", "(Ljava/lang/String;)V");
222 EXPECT_EQ(nullptr, method);
223 check_jni_abort_catcher.Check(check_jni ? "GetMethodID received NULL jclass"
224 : "java_class == null");
225 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
226 ASSERT_TRUE(jlnsme != nullptr);
227 method = env_->GetMethodID(jlnsme, nullptr, "(Ljava/lang/String;)V");
228 EXPECT_EQ(nullptr, method);
229 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
230 : "name == null");
231 method = env_->GetMethodID(jlnsme, "<init>", nullptr);
232 EXPECT_EQ(nullptr, method);
233 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
234 : "sig == null");
235
236 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
237 }
238
GetStaticMethodIdBadArgumentTest(bool check_jni)239 void GetStaticMethodIdBadArgumentTest(bool check_jni) {
240 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
241 CheckJniAbortCatcher check_jni_abort_catcher;
242
243 jmethodID method = env_->GetStaticMethodID(nullptr, "valueOf", "(I)Ljava/lang/String;");
244 EXPECT_EQ(nullptr, method);
245 check_jni_abort_catcher.Check(check_jni ? "GetStaticMethodID received NULL jclass"
246 : "java_class == null");
247 jclass jlstring = env_->FindClass("java/lang/String");
248 method = env_->GetStaticMethodID(jlstring, nullptr, "(I)Ljava/lang/String;");
249 EXPECT_EQ(nullptr, method);
250 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
251 : "name == null");
252 method = env_->GetStaticMethodID(jlstring, "valueOf", nullptr);
253 EXPECT_EQ(nullptr, method);
254 check_jni_abort_catcher.Check(check_jni ? "non-nullable const char* was NULL"
255 : "sig == null");
256
257 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
258 }
259
GetFromReflectedField_ToReflectedFieldBadArgumentTest(bool check_jni)260 void GetFromReflectedField_ToReflectedFieldBadArgumentTest(bool check_jni) {
261 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
262 CheckJniAbortCatcher check_jni_abort_catcher;
263
264 jclass c = env_->FindClass("java/lang/String");
265 ASSERT_NE(c, nullptr);
266 jfieldID fid = env_->GetFieldID(c, "count", "I");
267 ASSERT_NE(fid, nullptr);
268
269 // Check class argument for null argument, not checked in non-check JNI.
270 jobject field = env_->ToReflectedField(nullptr, fid, JNI_FALSE);
271 if (check_jni) {
272 EXPECT_EQ(field, nullptr);
273 check_jni_abort_catcher.Check("ToReflectedField received NULL jclass");
274 } else {
275 EXPECT_NE(field, nullptr);
276 }
277
278 field = env_->ToReflectedField(c, nullptr, JNI_FALSE);
279 EXPECT_EQ(field, nullptr);
280 check_jni_abort_catcher.Check(check_jni ? "jfieldID was NULL"
281 : "fid == null");
282
283 fid = env_->FromReflectedField(nullptr);
284 ASSERT_EQ(fid, nullptr);
285 check_jni_abort_catcher.Check(check_jni ? "expected non-null java.lang.reflect.Field"
286 : "jlr_field == null");
287
288 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
289 }
290
GetFromReflectedMethod_ToReflectedMethodBadArgumentTest(bool check_jni)291 void GetFromReflectedMethod_ToReflectedMethodBadArgumentTest(bool check_jni) {
292 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
293 CheckJniAbortCatcher check_jni_abort_catcher;
294
295 jclass c = env_->FindClass("java/lang/String");
296 ASSERT_NE(c, nullptr);
297 jmethodID mid = env_->GetMethodID(c, "<init>", "()V");
298 ASSERT_NE(mid, nullptr);
299
300 // Check class argument for null argument, not checked in non-check JNI.
301 jobject method = env_->ToReflectedMethod(nullptr, mid, JNI_FALSE);
302 if (check_jni) {
303 EXPECT_EQ(method, nullptr);
304 check_jni_abort_catcher.Check("ToReflectedMethod received NULL jclass");
305 } else {
306 EXPECT_NE(method, nullptr);
307 }
308
309 method = env_->ToReflectedMethod(c, nullptr, JNI_FALSE);
310 EXPECT_EQ(method, nullptr);
311 check_jni_abort_catcher.Check(check_jni ? "jmethodID was NULL"
312 : "mid == null");
313 mid = env_->FromReflectedMethod(method);
314 ASSERT_EQ(mid, nullptr);
315 check_jni_abort_catcher.Check(check_jni ? "expected non-null method" : "jlr_method == null");
316
317 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
318 }
319
RegisterAndUnregisterNativesBadArguments(bool check_jni,CheckJniAbortCatcher * check_jni_abort_catcher)320 void RegisterAndUnregisterNativesBadArguments(bool check_jni,
321 CheckJniAbortCatcher* check_jni_abort_catcher) {
322 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
323 // Passing a class of null is a failure.
324 {
325 JNINativeMethod methods[] = { };
326 EXPECT_EQ(env_->RegisterNatives(nullptr, methods, 0), JNI_ERR);
327 check_jni_abort_catcher->Check(check_jni ? "RegisterNatives received NULL jclass"
328 : "java_class == null");
329 }
330
331 // Passing methods as null is a failure.
332 jclass jlobject = env_->FindClass("java/lang/Object");
333 EXPECT_EQ(env_->RegisterNatives(jlobject, nullptr, 1), JNI_ERR);
334 check_jni_abort_catcher->Check("methods == null");
335
336 // Unregisters null is a failure.
337 EXPECT_EQ(env_->UnregisterNatives(nullptr), JNI_ERR);
338 check_jni_abort_catcher->Check(check_jni ? "UnregisterNatives received NULL jclass"
339 : "java_class == null");
340
341 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
342 }
343
344
GetPrimitiveArrayElementsOfWrongType(bool check_jni)345 void GetPrimitiveArrayElementsOfWrongType(bool check_jni) {
346 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
347 CheckJniAbortCatcher jni_abort_catcher;
348
349 jbooleanArray array = env_->NewBooleanArray(10);
350 jboolean is_copy;
351 EXPECT_EQ(env_->GetByteArrayElements(reinterpret_cast<jbyteArray>(array), &is_copy), nullptr);
352 jni_abort_catcher.Check(
353 check_jni ? "incompatible array type boolean[] expected byte[]"
354 : "attempt to get byte primitive array elements with an object of type boolean[]");
355 EXPECT_EQ(env_->GetShortArrayElements(reinterpret_cast<jshortArray>(array), &is_copy), nullptr);
356 jni_abort_catcher.Check(
357 check_jni ? "incompatible array type boolean[] expected short[]"
358 : "attempt to get short primitive array elements with an object of type boolean[]");
359 EXPECT_EQ(env_->GetCharArrayElements(reinterpret_cast<jcharArray>(array), &is_copy), nullptr);
360 jni_abort_catcher.Check(
361 check_jni ? "incompatible array type boolean[] expected char[]"
362 : "attempt to get char primitive array elements with an object of type boolean[]");
363 EXPECT_EQ(env_->GetIntArrayElements(reinterpret_cast<jintArray>(array), &is_copy), nullptr);
364 jni_abort_catcher.Check(
365 check_jni ? "incompatible array type boolean[] expected int[]"
366 : "attempt to get int primitive array elements with an object of type boolean[]");
367 EXPECT_EQ(env_->GetLongArrayElements(reinterpret_cast<jlongArray>(array), &is_copy), nullptr);
368 jni_abort_catcher.Check(
369 check_jni ? "incompatible array type boolean[] expected long[]"
370 : "attempt to get long primitive array elements with an object of type boolean[]");
371 EXPECT_EQ(env_->GetFloatArrayElements(reinterpret_cast<jfloatArray>(array), &is_copy), nullptr);
372 jni_abort_catcher.Check(
373 check_jni ? "incompatible array type boolean[] expected float[]"
374 : "attempt to get float primitive array elements with an object of type boolean[]");
375 EXPECT_EQ(env_->GetDoubleArrayElements(reinterpret_cast<jdoubleArray>(array), &is_copy), nullptr);
376 jni_abort_catcher.Check(
377 check_jni ? "incompatible array type boolean[] expected double[]"
378 : "attempt to get double primitive array elements with an object of type boolean[]");
379 jbyteArray array2 = env_->NewByteArray(10);
380 EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), &is_copy),
381 nullptr);
382 jni_abort_catcher.Check(
383 check_jni ? "incompatible array type byte[] expected boolean[]"
384 : "attempt to get boolean primitive array elements with an object of type byte[]");
385 jobject object = env_->NewStringUTF("Test String");
386 EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), &is_copy),
387 nullptr);
388 jni_abort_catcher.Check(
389 check_jni ? "jarray argument has non-array type: java.lang.String"
390 : "attempt to get boolean primitive array elements with an object of type java.lang.String");
391
392 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
393 }
394
ReleasePrimitiveArrayElementsOfWrongType(bool check_jni)395 void ReleasePrimitiveArrayElementsOfWrongType(bool check_jni) {
396 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
397 CheckJniAbortCatcher jni_abort_catcher;
398 {
399 jbooleanArray array = env_->NewBooleanArray(10);
400 ASSERT_TRUE(array != nullptr);
401 jboolean is_copy;
402 jboolean* elements = env_->GetBooleanArrayElements(array, &is_copy);
403 ASSERT_TRUE(elements != nullptr);
404 env_->ReleaseByteArrayElements(reinterpret_cast<jbyteArray>(array),
405 reinterpret_cast<jbyte*>(elements), 0);
406 jni_abort_catcher.Check(
407 check_jni ? "incompatible array type boolean[] expected byte[]"
408 : "attempt to release byte primitive array elements with an object of type boolean[]");
409 env_->ReleaseShortArrayElements(reinterpret_cast<jshortArray>(array),
410 reinterpret_cast<jshort*>(elements), 0);
411 jni_abort_catcher.Check(
412 check_jni ? "incompatible array type boolean[] expected short[]"
413 : "attempt to release short primitive array elements with an object of type boolean[]");
414 env_->ReleaseCharArrayElements(reinterpret_cast<jcharArray>(array),
415 reinterpret_cast<jchar*>(elements), 0);
416 jni_abort_catcher.Check(
417 check_jni ? "incompatible array type boolean[] expected char[]"
418 : "attempt to release char primitive array elements with an object of type boolean[]");
419 env_->ReleaseIntArrayElements(reinterpret_cast<jintArray>(array),
420 reinterpret_cast<jint*>(elements), 0);
421 jni_abort_catcher.Check(
422 check_jni ? "incompatible array type boolean[] expected int[]"
423 : "attempt to release int primitive array elements with an object of type boolean[]");
424 env_->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array),
425 reinterpret_cast<jlong*>(elements), 0);
426 jni_abort_catcher.Check(
427 check_jni ? "incompatible array type boolean[] expected long[]"
428 : "attempt to release long primitive array elements with an object of type boolean[]");
429 env_->ReleaseFloatArrayElements(reinterpret_cast<jfloatArray>(array),
430 reinterpret_cast<jfloat*>(elements), 0);
431 jni_abort_catcher.Check(
432 check_jni ? "incompatible array type boolean[] expected float[]"
433 : "attempt to release float primitive array elements with an object of type boolean[]");
434 env_->ReleaseDoubleArrayElements(reinterpret_cast<jdoubleArray>(array),
435 reinterpret_cast<jdouble*>(elements), 0);
436 jni_abort_catcher.Check(
437 check_jni ? "incompatible array type boolean[] expected double[]"
438 : "attempt to release double primitive array elements with an object of type boolean[]");
439
440 // Don't leak the elements array.
441 env_->ReleaseBooleanArrayElements(array, elements, 0);
442 }
443 {
444 jbyteArray array = env_->NewByteArray(10);
445 jboolean is_copy;
446 jbyte* elements = env_->GetByteArrayElements(array, &is_copy);
447
448 env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(array),
449 reinterpret_cast<jboolean*>(elements), 0);
450 jni_abort_catcher.Check(
451 check_jni ? "incompatible array type byte[] expected boolean[]"
452 : "attempt to release boolean primitive array elements with an object of type byte[]");
453 jobject object = env_->NewStringUTF("Test String");
454 env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(object),
455 reinterpret_cast<jboolean*>(elements), 0);
456 jni_abort_catcher.Check(
457 check_jni ? "jarray argument has non-array type: java.lang.String"
458 : "attempt to release boolean primitive array elements with an object of type "
459 "java.lang.String");
460
461 // Don't leak the elements array.
462 env_->ReleaseByteArrayElements(array, elements, 0);
463 }
464 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
465 }
466
GetReleasePrimitiveArrayCriticalOfWrongType(bool check_jni)467 void GetReleasePrimitiveArrayCriticalOfWrongType(bool check_jni) {
468 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
469 CheckJniAbortCatcher jni_abort_catcher;
470
471 jobject object = env_->NewStringUTF("Test String");
472 jboolean is_copy;
473 void* elements = env_->GetPrimitiveArrayCritical(reinterpret_cast<jarray>(object), &is_copy);
474 jni_abort_catcher.Check(check_jni ? "jarray argument has non-array type: java.lang.String"
475 : "expected primitive array, given java.lang.String");
476 env_->ReleasePrimitiveArrayCritical(reinterpret_cast<jarray>(object), elements, 0);
477 jni_abort_catcher.Check(check_jni ? "jarray argument has non-array type: java.lang.String"
478 : "expected primitive array, given java.lang.String");
479
480 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
481 }
482
GetPrimitiveArrayRegionElementsOfWrongType(bool check_jni)483 void GetPrimitiveArrayRegionElementsOfWrongType(bool check_jni) {
484 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
485 CheckJniAbortCatcher jni_abort_catcher;
486 constexpr size_t kLength = 10;
487 jbooleanArray array = env_->NewBooleanArray(kLength);
488 ASSERT_TRUE(array != nullptr);
489 jboolean elements[kLength];
490 env_->GetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
491 reinterpret_cast<jbyte*>(elements));
492 jni_abort_catcher.Check(
493 check_jni ? "incompatible array type boolean[] expected byte[]"
494 : "attempt to get region of byte primitive array elements with an object of type boolean[]");
495 env_->GetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
496 reinterpret_cast<jshort*>(elements));
497 jni_abort_catcher.Check(
498 check_jni ? "incompatible array type boolean[] expected short[]"
499 : "attempt to get region of short primitive array elements with an object of type boolean[]");
500 env_->GetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
501 reinterpret_cast<jchar*>(elements));
502 jni_abort_catcher.Check(
503 check_jni ? "incompatible array type boolean[] expected char[]"
504 : "attempt to get region of char primitive array elements with an object of type boolean[]");
505 env_->GetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
506 reinterpret_cast<jint*>(elements));
507 jni_abort_catcher.Check(
508 check_jni ? "incompatible array type boolean[] expected int[]"
509 : "attempt to get region of int primitive array elements with an object of type boolean[]");
510 env_->GetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
511 reinterpret_cast<jlong*>(elements));
512 jni_abort_catcher.Check(
513 check_jni ? "incompatible array type boolean[] expected long[]"
514 : "attempt to get region of long primitive array elements with an object of type boolean[]");
515 env_->GetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
516 reinterpret_cast<jfloat*>(elements));
517 jni_abort_catcher.Check(
518 check_jni ? "incompatible array type boolean[] expected float[]"
519 : "attempt to get region of float primitive array elements with an object of type boolean[]");
520 env_->GetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
521 reinterpret_cast<jdouble*>(elements));
522 jni_abort_catcher.Check(
523 check_jni ? "incompatible array type boolean[] expected double[]"
524 : "attempt to get region of double primitive array elements with an object of type boolean[]");
525 jbyteArray array2 = env_->NewByteArray(10);
526 env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
527 reinterpret_cast<jboolean*>(elements));
528 jni_abort_catcher.Check(
529 check_jni ? "incompatible array type byte[] expected boolean[]"
530 : "attempt to get region of boolean primitive array elements with an object of type byte[]");
531 jobject object = env_->NewStringUTF("Test String");
532 env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
533 reinterpret_cast<jboolean*>(elements));
534 jni_abort_catcher.Check(check_jni ? "jarray argument has non-array type: java.lang.String"
535 : "attempt to get region of boolean primitive array elements with an object of type "
536 "java.lang.String");
537
538 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
539 }
540
SetPrimitiveArrayRegionElementsOfWrongType(bool check_jni)541 void SetPrimitiveArrayRegionElementsOfWrongType(bool check_jni) {
542 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
543 CheckJniAbortCatcher jni_abort_catcher;
544 constexpr size_t kLength = 10;
545 jbooleanArray array = env_->NewBooleanArray(kLength);
546 ASSERT_TRUE(array != nullptr);
547 jboolean elements[kLength];
548 env_->SetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
549 reinterpret_cast<jbyte*>(elements));
550 jni_abort_catcher.Check(
551 check_jni ? "incompatible array type boolean[] expected byte[]"
552 : "attempt to set region of byte primitive array elements with an object of type boolean[]");
553 env_->SetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
554 reinterpret_cast<jshort*>(elements));
555 jni_abort_catcher.Check(
556 check_jni ? "incompatible array type boolean[] expected short[]"
557 : "attempt to set region of short primitive array elements with an object of type boolean[]");
558 env_->SetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
559 reinterpret_cast<jchar*>(elements));
560 jni_abort_catcher.Check(
561 check_jni ? "incompatible array type boolean[] expected char[]"
562 : "attempt to set region of char primitive array elements with an object of type boolean[]");
563 env_->SetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
564 reinterpret_cast<jint*>(elements));
565 jni_abort_catcher.Check(
566 check_jni ? "incompatible array type boolean[] expected int[]"
567 : "attempt to set region of int primitive array elements with an object of type boolean[]");
568 env_->SetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
569 reinterpret_cast<jlong*>(elements));
570 jni_abort_catcher.Check(
571 check_jni ? "incompatible array type boolean[] expected long[]"
572 : "attempt to set region of long primitive array elements with an object of type boolean[]");
573 env_->SetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
574 reinterpret_cast<jfloat*>(elements));
575 jni_abort_catcher.Check(
576 check_jni ? "incompatible array type boolean[] expected float[]"
577 : "attempt to set region of float primitive array elements with an object of type boolean[]");
578 env_->SetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
579 reinterpret_cast<jdouble*>(elements));
580 jni_abort_catcher.Check(
581 check_jni ? "incompatible array type boolean[] expected double[]"
582 : "attempt to set region of double primitive array elements with an object of type boolean[]");
583 jbyteArray array2 = env_->NewByteArray(10);
584 env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
585 reinterpret_cast<jboolean*>(elements));
586 jni_abort_catcher.Check(
587 check_jni ? "incompatible array type byte[] expected boolean[]"
588 : "attempt to set region of boolean primitive array elements with an object of type byte[]");
589 jobject object = env_->NewStringUTF("Test String");
590 env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
591 reinterpret_cast<jboolean*>(elements));
592 jni_abort_catcher.Check(check_jni ? "jarray argument has non-array type: java.lang.String"
593 : "attempt to set region of boolean primitive array elements with an object of type "
594 "java.lang.String");
595 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
596 }
597
NewObjectArrayBadArguments(bool check_jni)598 void NewObjectArrayBadArguments(bool check_jni) {
599 bool old_check_jni = vm_->SetCheckJniEnabled(check_jni);
600 CheckJniAbortCatcher jni_abort_catcher;
601
602 jclass element_class = env_->FindClass("java/lang/String");
603 ASSERT_NE(element_class, nullptr);
604
605 env_->NewObjectArray(-1, element_class, nullptr);
606 jni_abort_catcher.Check(check_jni ? "negative jsize: -1" : "negative array length: -1");
607
608 env_->NewObjectArray(std::numeric_limits<jint>::min(), element_class, nullptr);
609 jni_abort_catcher.Check(check_jni ? "negative jsize: -2147483648"
610 : "negative array length: -2147483648");
611
612 EXPECT_EQ(check_jni, vm_->SetCheckJniEnabled(old_check_jni));
613 }
614
SetUpForTest(bool direct,const char * method_name,const char * method_sig,void * native_fnptr)615 void SetUpForTest(bool direct, const char* method_name, const char* method_sig,
616 void* native_fnptr) {
617 // Initialize class loader and set generic JNI entrypoint.
618 // Note: this code is adapted from the jni_compiler_test, and taken with minimal modifications.
619 if (!runtime_->IsStarted()) {
620 {
621 ScopedObjectAccess soa(Thread::Current());
622 class_loader_ = LoadDex("MyClassNatives");
623 StackHandleScope<1> hs(soa.Self());
624 Handle<mirror::ClassLoader> loader(
625 hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader_)));
626 ObjPtr<mirror::Class> c = class_linker_->FindClass(soa.Self(), "LMyClassNatives;", loader);
627 const auto pointer_size = class_linker_->GetImagePointerSize();
628 ArtMethod* method = c->FindClassMethod(method_name, method_sig, pointer_size);
629 ASSERT_TRUE(method != nullptr) << method_name << " " << method_sig;
630 ASSERT_EQ(direct, method->IsDirect());
631 method->SetEntryPointFromQuickCompiledCode(class_linker_->GetRuntimeQuickGenericJniStub());
632 }
633 // Start runtime.
634 Thread::Current()->TransitionFromSuspendedToRunnable();
635 bool started = runtime_->Start();
636 CHECK(started);
637 }
638 // JNI operations after runtime start.
639 env_ = Thread::Current()->GetJniEnv();
640 jklass_ = env_->FindClass("MyClassNatives");
641 ASSERT_TRUE(jklass_ != nullptr) << method_name << " " << method_sig;
642
643 if (direct) {
644 jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
645 } else {
646 jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
647 }
648 ASSERT_TRUE(jmethod_ != nullptr) << method_name << " " << method_sig;
649
650 if (native_fnptr != nullptr) {
651 JNINativeMethod methods[] = { { method_name, method_sig, native_fnptr } };
652 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1))
653 << method_name << " " << method_sig;
654 } else {
655 env_->UnregisterNatives(jklass_);
656 }
657
658 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
659 jobj_ = env_->NewObject(jklass_, constructor);
660 ASSERT_TRUE(jobj_ != nullptr) << method_name << " " << method_sig;
661 }
662
663 JavaVMExt* vm_;
664 JNIEnv* env_;
665 jclass aioobe_;
666 jclass ase_;
667 jclass sioobe_;
668
669 jclass jklass_;
670 jobject jobj_;
671 jobject class_loader_;
672 jmethodID jmethod_;
673 };
674
TEST_F(JniInternalTest,AllocObject)675 TEST_F(JniInternalTest, AllocObject) {
676 jclass c = env_->FindClass("java/lang/String");
677 ASSERT_NE(c, nullptr);
678 jobject o = env_->AllocObject(c);
679 ASSERT_NE(o, nullptr);
680
681 // We have an instance of the class we asked for...
682 ASSERT_TRUE(env_->IsInstanceOf(o, c));
683 // ...whose fields haven't been initialized because
684 // we didn't call a constructor.
685 // Even with string compression empty string has `count == 0`.
686 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
687 }
688
TEST_F(JniInternalTest,GetVersion)689 TEST_F(JniInternalTest, GetVersion) {
690 ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
691 }
692
TEST_F(JniInternalTest,FindClass)693 TEST_F(JniInternalTest, FindClass) {
694 // This tests leads to warnings in the log.
695 ScopedLogSeverity sls(LogSeverity::ERROR);
696
697 FindClassTest(false);
698 FindClassTest(true);
699 }
700
TEST_F(JniInternalTest,GetFieldID)701 TEST_F(JniInternalTest, GetFieldID) {
702 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
703 ASSERT_NE(jlnsfe, nullptr);
704 jclass c = env_->FindClass("java/lang/String");
705 ASSERT_NE(c, nullptr);
706
707 // Wrong type.
708 jfieldID fid = env_->GetFieldID(c, "count", "J");
709 EXPECT_EQ(nullptr, fid);
710 ExpectException(jlnsfe);
711
712 // Wrong type where type doesn't exist.
713 fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;");
714 EXPECT_EQ(nullptr, fid);
715 ExpectException(jlnsfe);
716
717 // Wrong name.
718 fid = env_->GetFieldID(c, "Count", "I");
719 EXPECT_EQ(nullptr, fid);
720 ExpectException(jlnsfe);
721
722 // Good declared field lookup.
723 fid = env_->GetFieldID(c, "count", "I");
724 EXPECT_NE(nullptr, fid);
725 EXPECT_FALSE(env_->ExceptionCheck());
726
727 // Good superclass field lookup.
728 c = env_->FindClass("java/lang/StringBuilder");
729 fid = env_->GetFieldID(c, "count", "I");
730 EXPECT_NE(nullptr, fid);
731 EXPECT_NE(fid, nullptr);
732 EXPECT_FALSE(env_->ExceptionCheck());
733
734 // Not instance.
735 fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
736 EXPECT_EQ(nullptr, fid);
737 ExpectException(jlnsfe);
738
739 // Bad arguments.
740 GetFieldIdBadArgumentTest(false);
741 GetFieldIdBadArgumentTest(true);
742 }
743
TEST_F(JniInternalTest,GetStaticFieldID)744 TEST_F(JniInternalTest, GetStaticFieldID) {
745 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
746 ASSERT_NE(jlnsfe, nullptr);
747 jclass c = env_->FindClass("java/lang/String");
748 ASSERT_NE(c, nullptr);
749
750 // Wrong type.
751 jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J");
752 EXPECT_EQ(nullptr, fid);
753 ExpectException(jlnsfe);
754
755 // Wrong type where type doesn't exist.
756 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;");
757 EXPECT_EQ(nullptr, fid);
758 ExpectException(jlnsfe);
759
760 // Wrong name.
761 fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
762 EXPECT_EQ(nullptr, fid);
763 ExpectException(jlnsfe);
764
765 // Good declared field lookup.
766 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
767 EXPECT_NE(nullptr, fid);
768 EXPECT_NE(fid, nullptr);
769 EXPECT_FALSE(env_->ExceptionCheck());
770
771 // Not static.
772 fid = env_->GetStaticFieldID(c, "count", "I");
773 EXPECT_EQ(nullptr, fid);
774 ExpectException(jlnsfe);
775
776 // Bad arguments.
777 GetStaticFieldIdBadArgumentTest(false);
778 GetStaticFieldIdBadArgumentTest(true);
779 }
780
TEST_F(JniInternalTest,GetMethodID)781 TEST_F(JniInternalTest, GetMethodID) {
782 jclass jlobject = env_->FindClass("java/lang/Object");
783 jclass jlstring = env_->FindClass("java/lang/String");
784 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
785 jclass jncrbc = env_->FindClass("java/nio/channels/ReadableByteChannel");
786
787 // Check that no exceptions are pending.
788 ASSERT_FALSE(env_->ExceptionCheck());
789
790 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
791 // a pending exception.
792 jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
793 EXPECT_EQ(nullptr, method);
794 ExpectException(jlnsme);
795
796 // Check that java.lang.Object.equals() does exist.
797 method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
798 EXPECT_NE(nullptr, method);
799 EXPECT_FALSE(env_->ExceptionCheck());
800
801 // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
802 // method is static.
803 method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
804 EXPECT_EQ(nullptr, method);
805 ExpectException(jlnsme);
806
807 // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor.
808 method = env_->GetMethodID(jlnsme, "<init>", "(Ljava/lang/String;)V");
809 EXPECT_NE(nullptr, method);
810 EXPECT_FALSE(env_->ExceptionCheck());
811
812 // Check that GetMethodID can find a interface method inherited from another interface.
813 method = env_->GetMethodID(jncrbc, "close", "()V");
814 EXPECT_NE(nullptr, method);
815 EXPECT_FALSE(env_->ExceptionCheck());
816
817 // Bad arguments.
818 GetMethodIdBadArgumentTest(false);
819 GetMethodIdBadArgumentTest(true);
820 }
821
TEST_F(JniInternalTest,CallVoidMethodNullReceiver)822 TEST_F(JniInternalTest, CallVoidMethodNullReceiver) {
823 jclass jlobject = env_->FindClass("java/lang/Object");
824 jmethodID method;
825
826 // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor.
827 method = env_->GetMethodID(jlobject, "<init>", "()V");
828 EXPECT_NE(nullptr, method);
829 EXPECT_FALSE(env_->ExceptionCheck());
830
831 // Null object to CallVoidMethod.
832 CheckJniAbortCatcher check_jni_abort_catcher;
833 env_->CallVoidMethod(nullptr, method);
834 check_jni_abort_catcher.Check("null");
835 }
836
TEST_F(JniInternalTest,CallVarArgMethodBadPrimitive)837 TEST_F(JniInternalTest, CallVarArgMethodBadPrimitive) {
838 // Check that bad primitive values cause check JNI to abort when
839 // passed out-of-range primitive value var args. As var args can't
840 // differentiate type sizes less than an int, and this isn't
841 // corrected by JNI, this helps ensure JNI code is valid.
842 #define DoCall(boxed_type, shorty, c_type, bad_value) \
843 { \
844 jclass prim_class = env_->FindClass("java/lang/" #boxed_type); \
845 jmethodID method = env_->GetStaticMethodID(prim_class, "valueOf", \
846 "(" #shorty ")Ljava/lang/" #boxed_type ";"); \
847 EXPECT_NE(nullptr, method); \
848 EXPECT_FALSE(env_->ExceptionCheck()); \
849 CheckJniAbortCatcher check_jni_abort_catcher; \
850 env_->CallStaticObjectMethod(prim_class, method, bad_value); \
851 check_jni_abort_catcher.Check("unexpected " #c_type " value: " #bad_value); \
852 }
853
854 DoCall(Boolean, Z, jboolean, 2);
855 DoCall(Byte, B, jbyte, 128);
856 DoCall(Byte, B, jbyte, -129);
857 DoCall(Short, S, jshort, 32768);
858 DoCall(Short, S, jshort, -32769);
859 DoCall(Character, C, jchar, 65536);
860 DoCall(Character, C, jchar, -1);
861 #undef DoCall
862 }
863
TEST_F(JniInternalTest,CallJValueMethodBadPrimitive)864 TEST_F(JniInternalTest, CallJValueMethodBadPrimitive) {
865 // Check that bad primitive values, passed as jvalues, cause check
866 // JNI to abort. Unlike with var args, sizes less than an int should
867 // be truncated or sign extended and not cause an abort except for
868 // jbooleans that are passed as bytes.
869 #define DoFailCall(boxed_type, shorty, c_type, bad_value) \
870 { \
871 jclass prim_class = env_->FindClass("java/lang/" #boxed_type); \
872 jmethodID method = env_->GetStaticMethodID(prim_class, "valueOf", \
873 "(" #shorty ")Ljava/lang/" #boxed_type ";"); \
874 EXPECT_NE(nullptr, method); \
875 EXPECT_FALSE(env_->ExceptionCheck()); \
876 CheckJniAbortCatcher check_jni_abort_catcher; \
877 jvalue jval; \
878 jval.i = bad_value; \
879 env_->CallStaticObjectMethodA(prim_class, method, &jval); \
880 check_jni_abort_catcher.Check("unexpected " #c_type " value: " #bad_value); \
881 }
882 #define DoGoodCall(boxed_type, shorty, c_type, bad_value) \
883 { \
884 jclass prim_class = env_->FindClass("java/lang/" #boxed_type); \
885 jmethodID method = env_->GetStaticMethodID(prim_class, "valueOf", \
886 "(" #shorty ")Ljava/lang/" #boxed_type ";"); \
887 EXPECT_NE(nullptr, method); \
888 EXPECT_FALSE(env_->ExceptionCheck()); \
889 jvalue jval; \
890 jval.i = bad_value; \
891 env_->CallStaticObjectMethodA(prim_class, method, &jval); \
892 }
893
894 DoFailCall(Boolean, Z, jboolean, 2);
895 DoGoodCall(Byte, B, jbyte, 128);
896 DoGoodCall(Byte, B, jbyte, -129);
897 DoGoodCall(Short, S, jshort, 32768);
898 DoGoodCall(Short, S, jshort, -32769);
899 DoGoodCall(Character, C, jchar, 65536);
900 DoGoodCall(Character, C, jchar, -1);
901 #undef DoCall
902 }
903
TEST_F(JniInternalTest,GetStaticMethodID)904 TEST_F(JniInternalTest, GetStaticMethodID) {
905 jclass jlobject = env_->FindClass("java/lang/Object");
906 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
907
908 // Check that no exceptions are pending
909 ASSERT_FALSE(env_->ExceptionCheck());
910
911 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
912 // a pending exception
913 jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
914 EXPECT_EQ(nullptr, method);
915 ExpectException(jlnsme);
916
917 // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
918 // the method is not static
919 method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
920 EXPECT_EQ(nullptr, method);
921 ExpectException(jlnsme);
922
923 // Check that java.lang.String.valueOf(int) does exist
924 jclass jlstring = env_->FindClass("java/lang/String");
925 method = env_->GetStaticMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
926 EXPECT_NE(nullptr, method);
927 EXPECT_FALSE(env_->ExceptionCheck());
928
929 // Bad arguments.
930 GetStaticMethodIdBadArgumentTest(false);
931 GetStaticMethodIdBadArgumentTest(true);
932 }
933
GetLocalsCapacity(JNIEnv * env)934 static size_t GetLocalsCapacity(JNIEnv* env) {
935 ScopedObjectAccess soa(Thread::Current());
936 return reinterpret_cast<JNIEnvExt*>(env)->GetLocalsCapacity();
937 }
938
TEST_F(JniInternalTest,FromReflectedField_ToReflectedField)939 TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) {
940 jclass jlrField = env_->FindClass("java/lang/reflect/Field");
941 jclass c = env_->FindClass("java/lang/String");
942 ASSERT_NE(c, nullptr);
943 jfieldID fid = env_->GetFieldID(c, "count", "I");
944 ASSERT_NE(fid, nullptr);
945 // Turn the fid into a java.lang.reflect.Field...
946 jobject field = env_->ToReflectedField(c, fid, JNI_FALSE);
947 size_t capacity_before = GetLocalsCapacity(env_);
948 for (size_t i = 0; i <= 10; ++i) {
949 // Regression test for b/18396311, ToReflectedField leaking local refs causing a local
950 // reference table overflows with 512 references to ArtField
951 env_->DeleteLocalRef(env_->ToReflectedField(c, fid, JNI_FALSE));
952 }
953 size_t capacity_after = GetLocalsCapacity(env_);
954 ASSERT_EQ(capacity_before, capacity_after);
955
956 ASSERT_NE(c, nullptr);
957 ASSERT_TRUE(env_->IsInstanceOf(field, jlrField));
958 // ...and back again.
959 jfieldID fid2 = env_->FromReflectedField(field);
960 ASSERT_NE(fid2, nullptr);
961 // Make sure we can actually use it.
962 jstring s = env_->NewStringUTF("poop");
963 if (mirror::kUseStringCompression) {
964 ASSERT_EQ(mirror::String::GetFlaggedCount(4, /* compressible= */ true),
965 env_->GetIntField(s, fid2));
966 // Create incompressible string
967 jstring s_16 = env_->NewStringUTF("\u0444\u0444");
968 ASSERT_EQ(mirror::String::GetFlaggedCount(2, /* compressible= */ false),
969 env_->GetIntField(s_16, fid2));
970 } else {
971 ASSERT_EQ(4, env_->GetIntField(s, fid2));
972 }
973 // Bad arguments.
974 GetFromReflectedField_ToReflectedFieldBadArgumentTest(false);
975 GetFromReflectedField_ToReflectedFieldBadArgumentTest(true);
976 }
977
TEST_F(JniInternalTest,FromReflectedMethod_ToReflectedMethod)978 TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
979 jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
980 ASSERT_NE(jlrMethod, nullptr);
981 jclass jlrConstructor = env_->FindClass("java/lang/reflect/Constructor");
982 ASSERT_NE(jlrConstructor, nullptr);
983 jclass c = env_->FindClass("java/lang/String");
984 ASSERT_NE(c, nullptr);
985
986 jmethodID mid = env_->GetMethodID(c, "<init>", "()V");
987 ASSERT_NE(mid, nullptr);
988 // Turn the mid into a java.lang.reflect.Constructor...
989 jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
990 size_t capacity_before = GetLocalsCapacity(env_);
991 for (size_t i = 0; i <= 10; ++i) {
992 // Regression test for b/18396311, ToReflectedMethod leaking local refs causing a local
993 // reference table overflows with 512 references to ArtMethod
994 env_->DeleteLocalRef(env_->ToReflectedMethod(c, mid, JNI_FALSE));
995 }
996 size_t capacity_after = GetLocalsCapacity(env_);
997 ASSERT_EQ(capacity_before, capacity_after);
998 ASSERT_NE(method, nullptr);
999 ASSERT_TRUE(env_->IsInstanceOf(method, jlrConstructor));
1000 // ...and back again.
1001 jmethodID mid2 = env_->FromReflectedMethod(method);
1002 ASSERT_NE(mid2, nullptr);
1003 // Make sure we can actually use it.
1004 jstring s = reinterpret_cast<jstring>(env_->AllocObject(c));
1005 ASSERT_NE(s, nullptr);
1006 env_->CallVoidMethod(s, mid2);
1007 ASSERT_EQ(JNI_FALSE, env_->ExceptionCheck());
1008 env_->ExceptionClear();
1009
1010 mid = env_->GetMethodID(c, "length", "()I");
1011 ASSERT_NE(mid, nullptr);
1012 // Turn the mid into a java.lang.reflect.Method...
1013 method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
1014 ASSERT_NE(method, nullptr);
1015 ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
1016 // ...and back again.
1017 mid2 = env_->FromReflectedMethod(method);
1018 ASSERT_NE(mid2, nullptr);
1019 // Make sure we can actually use it.
1020 s = env_->NewStringUTF("poop");
1021 ASSERT_NE(s, nullptr);
1022 ASSERT_EQ(4, env_->CallIntMethod(s, mid2));
1023
1024 // Bad arguments.
1025 GetFromReflectedMethod_ToReflectedMethodBadArgumentTest(false);
1026 GetFromReflectedMethod_ToReflectedMethodBadArgumentTest(true);
1027 }
1028
BogusMethod()1029 static void BogusMethod() {
1030 // You can't pass null function pointers to RegisterNatives.
1031 }
1032
TEST_F(JniInternalTest,RegisterAndUnregisterNatives)1033 TEST_F(JniInternalTest, RegisterAndUnregisterNatives) {
1034 jclass jlobject = env_->FindClass("java/lang/Object");
1035 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
1036 void* native_function = reinterpret_cast<void*>(BogusMethod);
1037
1038 // Check that no exceptions are pending.
1039 ASSERT_FALSE(env_->ExceptionCheck());
1040
1041 // The following can print errors to the log we'd like to ignore.
1042 {
1043 ScopedLogSeverity sls(LogSeverity::FATAL);
1044 // Check that registering method without name causes a NoSuchMethodError.
1045 {
1046 JNINativeMethod methods[] = { { nullptr, "()V", native_function } };
1047 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
1048 }
1049 ExpectException(jlnsme);
1050
1051 // Check that registering method without signature causes a NoSuchMethodError.
1052 {
1053 JNINativeMethod methods[] = { { "notify", nullptr, native_function } };
1054 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
1055 }
1056 ExpectException(jlnsme);
1057
1058 // Check that registering method without function causes a NoSuchMethodError.
1059 {
1060 JNINativeMethod methods[] = { { "notify", "()V", nullptr } };
1061 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
1062 }
1063 ExpectException(jlnsme);
1064
1065 // Check that registering to a non-existent java.lang.Object.foo() causes a NoSuchMethodError.
1066 {
1067 JNINativeMethod methods[] = { { "foo", "()V", native_function } };
1068 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
1069 }
1070 ExpectException(jlnsme);
1071
1072 // Check that registering non-native methods causes a NoSuchMethodError.
1073 {
1074 JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", native_function } };
1075 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
1076 }
1077 ExpectException(jlnsme);
1078 }
1079
1080 // Check that registering native methods is successful.
1081 {
1082 JNINativeMethod methods[] = { { "notify", "()V", native_function } };
1083 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_OK);
1084 }
1085 EXPECT_FALSE(env_->ExceptionCheck());
1086 EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
1087
1088 // Check that registering no methods isn't a failure.
1089 {
1090 JNINativeMethod methods[] = { };
1091 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 0), JNI_OK);
1092 }
1093 EXPECT_FALSE(env_->ExceptionCheck());
1094 EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
1095
1096 // Check that registering a -ve number of methods is a failure.
1097 CheckJniAbortCatcher check_jni_abort_catcher;
1098 for (int i = -10; i < 0; ++i) {
1099 JNINativeMethod methods[] = { };
1100 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, i), JNI_ERR);
1101 check_jni_abort_catcher.Check("negative method count: ");
1102 }
1103 EXPECT_FALSE(env_->ExceptionCheck());
1104
1105 // Unregistering a class with no natives is a warning.
1106 EXPECT_EQ(env_->UnregisterNatives(jlnsme), JNI_OK);
1107
1108 RegisterAndUnregisterNativesBadArguments(false, &check_jni_abort_catcher);
1109 RegisterAndUnregisterNativesBadArguments(true, &check_jni_abort_catcher);
1110 }
1111
1112 #define EXPECT_PRIMITIVE_ARRAY(new_fn, \
1113 get_region_fn, \
1114 set_region_fn, \
1115 get_elements_fn, \
1116 release_elements_fn, \
1117 scalar_type, \
1118 expected_class_descriptor) \
1119 jsize size = 4; \
1120 \
1121 { \
1122 CheckJniAbortCatcher jni_abort_catcher; \
1123 down_cast<JNIEnvExt*>(env_)->SetCheckJniEnabled(false); \
1124 /* Allocate an negative sized array and check it has the right failure type. */ \
1125 EXPECT_EQ(env_->new_fn(-1), nullptr); \
1126 jni_abort_catcher.Check("negative array length: -1"); \
1127 EXPECT_EQ(env_->new_fn(std::numeric_limits<jint>::min()), nullptr); \
1128 jni_abort_catcher.Check("negative array length: -2147483648"); \
1129 /* Pass the array as null. */ \
1130 EXPECT_EQ(0, env_->GetArrayLength(nullptr)); \
1131 jni_abort_catcher.Check("java_array == null"); \
1132 env_->get_region_fn(nullptr, 0, 0, nullptr); \
1133 jni_abort_catcher.Check("java_array == null"); \
1134 env_->set_region_fn(nullptr, 0, 0, nullptr); \
1135 jni_abort_catcher.Check("java_array == null"); \
1136 env_->get_elements_fn(nullptr, nullptr); \
1137 jni_abort_catcher.Check("java_array == null"); \
1138 env_->release_elements_fn(nullptr, nullptr, 0); \
1139 jni_abort_catcher.Check("java_array == null"); \
1140 /* Pass the elements for region as null. */ \
1141 scalar_type ## Array a = env_->new_fn(size); \
1142 env_->get_region_fn(a, 0, size, nullptr); \
1143 jni_abort_catcher.Check("buf == null"); \
1144 env_->set_region_fn(a, 0, size, nullptr); \
1145 jni_abort_catcher.Check("buf == null"); \
1146 down_cast<JNIEnvExt*>(env_)->SetCheckJniEnabled(true); \
1147 } \
1148 /* Allocate an array and check it has the right type and length. */ \
1149 scalar_type ## Array a = env_->new_fn(size); \
1150 EXPECT_NE(a, nullptr); \
1151 EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
1152 EXPECT_EQ(size, env_->GetArrayLength(a)); \
1153 \
1154 /* GetPrimitiveArrayRegion/SetPrimitiveArrayRegion */ \
1155 /* AIOOBE for negative start offset. */ \
1156 env_->get_region_fn(a, -1, 1, nullptr); \
1157 ExpectException(aioobe_); \
1158 env_->set_region_fn(a, -1, 1, nullptr); \
1159 ExpectException(aioobe_); \
1160 \
1161 /* AIOOBE for negative length. */ \
1162 env_->get_region_fn(a, 0, -1, nullptr); \
1163 ExpectException(aioobe_); \
1164 env_->set_region_fn(a, 0, -1, nullptr); \
1165 ExpectException(aioobe_); \
1166 \
1167 /* AIOOBE for buffer overrun. */ \
1168 env_->get_region_fn(a, size - 1, size, nullptr); \
1169 ExpectException(aioobe_); \
1170 env_->set_region_fn(a, size - 1, size, nullptr); \
1171 ExpectException(aioobe_); \
1172 \
1173 /* Regression test against integer overflow in range check. */ \
1174 env_->get_region_fn(a, 0x7fffffff, 0x7fffffff, nullptr); \
1175 ExpectException(aioobe_); \
1176 env_->set_region_fn(a, 0x7fffffff, 0x7fffffff, nullptr); \
1177 ExpectException(aioobe_); \
1178 \
1179 /* It's okay for the buffer to be null as long as the length is 0. */ \
1180 env_->get_region_fn(a, 2, 0, nullptr); \
1181 /* Even if the offset is invalid... */ \
1182 env_->get_region_fn(a, 123, 0, nullptr); \
1183 ExpectException(aioobe_); \
1184 \
1185 /* It's okay for the buffer to be null as long as the length is 0. */ \
1186 env_->set_region_fn(a, 2, 0, nullptr); \
1187 /* Even if the offset is invalid... */ \
1188 env_->set_region_fn(a, 123, 0, nullptr); \
1189 ExpectException(aioobe_); \
1190 \
1191 /* Prepare a couple of buffers. */ \
1192 /* NOLINT, no parentheses around scalar_type. */ \
1193 std::unique_ptr<scalar_type[]> src_buf(new scalar_type[size]); /* NOLINT */ \
1194 std::unique_ptr<scalar_type[]> dst_buf(new scalar_type[size]); /* NOLINT */ \
1195 for (jsize i = 0; i < size; ++i) { src_buf[i] = scalar_type(i); } \
1196 for (jsize i = 0; i < size; ++i) { dst_buf[i] = scalar_type(-1); } \
1197 \
1198 /* Copy all of src_buf onto the heap. */ \
1199 env_->set_region_fn(a, 0, size, &src_buf[0]); \
1200 /* Copy back only part. */ \
1201 env_->get_region_fn(a, 1, size - 2, &dst_buf[1]); \
1202 EXPECT_NE(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
1203 << "short copy equal"; \
1204 /* Copy the missing pieces. */ \
1205 env_->get_region_fn(a, 0, 1, &dst_buf[0]); \
1206 env_->get_region_fn(a, size - 1, 1, &dst_buf[size - 1]); \
1207 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
1208 << "fixed copy not equal"; \
1209 /* Copy back the whole array. */ \
1210 env_->get_region_fn(a, 0, size, &dst_buf[0]); \
1211 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
1212 << "full copy not equal"; \
1213 /* GetPrimitiveArrayCritical */ \
1214 void* v = env_->GetPrimitiveArrayCritical(a, nullptr); \
1215 EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) \
1216 << "GetPrimitiveArrayCritical not equal"; \
1217 env_->ReleasePrimitiveArrayCritical(a, v, 0); \
1218 /* GetXArrayElements */ \
1219 scalar_type* xs = env_->get_elements_fn(a, nullptr); /* NOLINT, scalar_type */ \
1220 EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) \
1221 << # get_elements_fn " not equal"; \
1222 env_->release_elements_fn(a, xs, 0); \
1223
TEST_F(JniInternalTest,BooleanArrays)1224 TEST_F(JniInternalTest, BooleanArrays) {
1225 EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, GetBooleanArrayRegion, SetBooleanArrayRegion,
1226 GetBooleanArrayElements, ReleaseBooleanArrayElements, jboolean, "[Z");
1227 }
TEST_F(JniInternalTest,ByteArrays)1228 TEST_F(JniInternalTest, ByteArrays) {
1229 EXPECT_PRIMITIVE_ARRAY(NewByteArray, GetByteArrayRegion, SetByteArrayRegion,
1230 GetByteArrayElements, ReleaseByteArrayElements, jbyte, "[B");
1231 }
TEST_F(JniInternalTest,CharArrays)1232 TEST_F(JniInternalTest, CharArrays) {
1233 EXPECT_PRIMITIVE_ARRAY(NewCharArray, GetCharArrayRegion, SetCharArrayRegion,
1234 GetCharArrayElements, ReleaseCharArrayElements, jchar, "[C");
1235 }
TEST_F(JniInternalTest,DoubleArrays)1236 TEST_F(JniInternalTest, DoubleArrays) {
1237 EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, GetDoubleArrayRegion, SetDoubleArrayRegion,
1238 GetDoubleArrayElements, ReleaseDoubleArrayElements, jdouble, "[D");
1239 }
TEST_F(JniInternalTest,FloatArrays)1240 TEST_F(JniInternalTest, FloatArrays) {
1241 EXPECT_PRIMITIVE_ARRAY(NewFloatArray, GetFloatArrayRegion, SetFloatArrayRegion,
1242 GetFloatArrayElements, ReleaseFloatArrayElements, jfloat, "[F");
1243 }
TEST_F(JniInternalTest,IntArrays)1244 TEST_F(JniInternalTest, IntArrays) {
1245 EXPECT_PRIMITIVE_ARRAY(NewIntArray, GetIntArrayRegion, SetIntArrayRegion,
1246 GetIntArrayElements, ReleaseIntArrayElements, jint, "[I");
1247 }
TEST_F(JniInternalTest,LongArrays)1248 TEST_F(JniInternalTest, LongArrays) {
1249 EXPECT_PRIMITIVE_ARRAY(NewLongArray, GetLongArrayRegion, SetLongArrayRegion,
1250 GetLongArrayElements, ReleaseLongArrayElements, jlong, "[J");
1251 }
TEST_F(JniInternalTest,ShortArrays)1252 TEST_F(JniInternalTest, ShortArrays) {
1253 EXPECT_PRIMITIVE_ARRAY(NewShortArray, GetShortArrayRegion, SetShortArrayRegion,
1254 GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S");
1255 }
1256
TEST_F(JniInternalTest,GetPrimitiveArrayElementsOfWrongType)1257 TEST_F(JniInternalTest, GetPrimitiveArrayElementsOfWrongType) {
1258 GetPrimitiveArrayElementsOfWrongType(false);
1259 GetPrimitiveArrayElementsOfWrongType(true);
1260 }
1261
TEST_F(JniInternalTest,ReleasePrimitiveArrayElementsOfWrongType)1262 TEST_F(JniInternalTest, ReleasePrimitiveArrayElementsOfWrongType) {
1263 ReleasePrimitiveArrayElementsOfWrongType(false);
1264 ReleasePrimitiveArrayElementsOfWrongType(true);
1265 }
1266
TEST_F(JniInternalTest,GetReleasePrimitiveArrayCriticalOfWrongType)1267 TEST_F(JniInternalTest, GetReleasePrimitiveArrayCriticalOfWrongType) {
1268 GetReleasePrimitiveArrayCriticalOfWrongType(false);
1269 GetReleasePrimitiveArrayCriticalOfWrongType(true);
1270 }
1271
TEST_F(JniInternalTest,GetPrimitiveArrayRegionElementsOfWrongType)1272 TEST_F(JniInternalTest, GetPrimitiveArrayRegionElementsOfWrongType) {
1273 GetPrimitiveArrayRegionElementsOfWrongType(false);
1274 GetPrimitiveArrayRegionElementsOfWrongType(true);
1275 }
1276
TEST_F(JniInternalTest,SetPrimitiveArrayRegionElementsOfWrongType)1277 TEST_F(JniInternalTest, SetPrimitiveArrayRegionElementsOfWrongType) {
1278 SetPrimitiveArrayRegionElementsOfWrongType(false);
1279 SetPrimitiveArrayRegionElementsOfWrongType(true);
1280 }
1281
TEST_F(JniInternalTest,NewObjectArray)1282 TEST_F(JniInternalTest, NewObjectArray) {
1283 jclass element_class = env_->FindClass("java/lang/String");
1284 ASSERT_NE(element_class, nullptr);
1285 jclass array_class = env_->FindClass("[Ljava/lang/String;");
1286 ASSERT_NE(array_class, nullptr);
1287
1288 jobjectArray a = env_->NewObjectArray(0, element_class, nullptr);
1289 EXPECT_NE(a, nullptr);
1290 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
1291 EXPECT_EQ(0, env_->GetArrayLength(a));
1292
1293 a = env_->NewObjectArray(1, element_class, nullptr);
1294 EXPECT_NE(a, nullptr);
1295 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
1296 EXPECT_EQ(1, env_->GetArrayLength(a));
1297 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), nullptr));
1298
1299 // Negative array length checks.
1300 NewObjectArrayBadArguments(false);
1301 NewObjectArrayBadArguments(true);
1302 }
1303
TEST_F(JniInternalTest,NewObjectArrayWithPrimitiveClasses)1304 TEST_F(JniInternalTest, NewObjectArrayWithPrimitiveClasses) {
1305 const char* primitive_descriptors = "VZBSCIJFD";
1306 const char* primitive_names[] = {
1307 "void", "boolean", "byte", "short", "char", "int", "long", "float", "double"
1308 };
1309 ASSERT_EQ(strlen(primitive_descriptors), arraysize(primitive_names));
1310
1311 bool old_check_jni = vm_->SetCheckJniEnabled(false);
1312 CheckJniAbortCatcher jni_abort_catcher;
1313 for (size_t i = 0; i < strlen(primitive_descriptors); ++i) {
1314 env_->NewObjectArray(0, nullptr, nullptr);
1315 jni_abort_catcher.Check("element_jclass == null");
1316 jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]);
1317 env_->NewObjectArray(1, primitive_class, nullptr);
1318 std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i]));
1319 jni_abort_catcher.Check(error_msg.c_str());
1320 }
1321 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1322 for (size_t i = 0; i < strlen(primitive_descriptors); ++i) {
1323 env_->NewObjectArray(0, nullptr, nullptr);
1324 jni_abort_catcher.Check("NewObjectArray received NULL jclass");
1325 jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]);
1326 env_->NewObjectArray(1, primitive_class, nullptr);
1327 std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i]));
1328 jni_abort_catcher.Check(error_msg.c_str());
1329 }
1330 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
1331 }
1332
TEST_F(JniInternalTest,NewObjectArrayWithInitialValue)1333 TEST_F(JniInternalTest, NewObjectArrayWithInitialValue) {
1334 jclass element_class = env_->FindClass("java/lang/String");
1335 ASSERT_NE(element_class, nullptr);
1336 jclass array_class = env_->FindClass("[Ljava/lang/String;");
1337 ASSERT_NE(array_class, nullptr);
1338
1339 jstring s = env_->NewStringUTF("poop");
1340 jobjectArray a = env_->NewObjectArray(2, element_class, s);
1341 EXPECT_NE(a, nullptr);
1342 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
1343 EXPECT_EQ(2, env_->GetArrayLength(a));
1344 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s));
1345 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 1), s));
1346
1347 // Attempt to incorrect create an array of strings with initial value of string arrays.
1348 CheckJniAbortCatcher jni_abort_catcher;
1349 env_->NewObjectArray(2, element_class, a);
1350 jni_abort_catcher.Check("cannot assign object of type 'java.lang.String[]' to array with element "
1351 "type of 'java.lang.String'");
1352 }
1353
TEST_F(JniInternalTest,GetArrayLength)1354 TEST_F(JniInternalTest, GetArrayLength) {
1355 // Already tested in NewObjectArray/NewPrimitiveArray except for null.
1356 CheckJniAbortCatcher jni_abort_catcher;
1357 bool old_check_jni = vm_->SetCheckJniEnabled(false);
1358 EXPECT_EQ(0, env_->GetArrayLength(nullptr));
1359 jni_abort_catcher.Check("java_array == null");
1360 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1361 EXPECT_EQ(JNI_ERR, env_->GetArrayLength(nullptr));
1362 jni_abort_catcher.Check("jarray was NULL");
1363 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
1364 }
1365
TEST_F(JniInternalTest,GetObjectClass)1366 TEST_F(JniInternalTest, GetObjectClass) {
1367 jclass string_class = env_->FindClass("java/lang/String");
1368 ASSERT_NE(string_class, nullptr);
1369 jclass class_class = env_->FindClass("java/lang/Class");
1370 ASSERT_NE(class_class, nullptr);
1371
1372 jstring s = env_->NewStringUTF("poop");
1373 jclass c = env_->GetObjectClass(s);
1374 ASSERT_TRUE(env_->IsSameObject(string_class, c));
1375
1376 jclass c2 = env_->GetObjectClass(c);
1377 ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2)));
1378
1379 // Null as object should fail.
1380 CheckJniAbortCatcher jni_abort_catcher;
1381 EXPECT_EQ(env_->GetObjectClass(nullptr), nullptr);
1382 jni_abort_catcher.Check("java_object == null");
1383 }
1384
TEST_F(JniInternalTest,GetSuperclass)1385 TEST_F(JniInternalTest, GetSuperclass) {
1386 jclass object_class = env_->FindClass("java/lang/Object");
1387 ASSERT_NE(object_class, nullptr);
1388 jclass string_class = env_->FindClass("java/lang/String");
1389 ASSERT_NE(string_class, nullptr);
1390 jclass runnable_interface = env_->FindClass("java/lang/Runnable");
1391 ASSERT_NE(runnable_interface, nullptr);
1392 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
1393 ASSERT_EQ(env_->GetSuperclass(object_class), nullptr);
1394 ASSERT_EQ(env_->GetSuperclass(runnable_interface), nullptr);
1395
1396 // Null as class should fail.
1397 CheckJniAbortCatcher jni_abort_catcher;
1398 bool old_check_jni = vm_->SetCheckJniEnabled(false);
1399 EXPECT_EQ(env_->GetSuperclass(nullptr), nullptr);
1400 jni_abort_catcher.Check("java_class == null");
1401 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1402 EXPECT_EQ(env_->GetSuperclass(nullptr), nullptr);
1403 jni_abort_catcher.Check("GetSuperclass received NULL jclass");
1404 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
1405 }
1406
TEST_F(JniInternalTest,IsAssignableFrom)1407 TEST_F(JniInternalTest, IsAssignableFrom) {
1408 jclass object_class = env_->FindClass("java/lang/Object");
1409 ASSERT_NE(object_class, nullptr);
1410 jclass string_class = env_->FindClass("java/lang/String");
1411 ASSERT_NE(string_class, nullptr);
1412
1413 // A superclass is assignable from an instance of its
1414 // subclass but not vice versa.
1415 ASSERT_TRUE(env_->IsAssignableFrom(string_class, object_class));
1416 ASSERT_FALSE(env_->IsAssignableFrom(object_class, string_class));
1417
1418 jclass charsequence_interface = env_->FindClass("java/lang/CharSequence");
1419 ASSERT_NE(charsequence_interface, nullptr);
1420
1421 // An interface is assignable from an instance of an implementing
1422 // class but not vice versa.
1423 ASSERT_TRUE(env_->IsAssignableFrom(string_class, charsequence_interface));
1424 ASSERT_FALSE(env_->IsAssignableFrom(charsequence_interface, string_class));
1425
1426 // Check that arrays are covariant.
1427 jclass string_array_class = env_->FindClass("[Ljava/lang/String;");
1428 ASSERT_NE(string_array_class, nullptr);
1429 jclass object_array_class = env_->FindClass("[Ljava/lang/Object;");
1430 ASSERT_NE(object_array_class, nullptr);
1431 ASSERT_TRUE(env_->IsAssignableFrom(string_array_class, object_array_class));
1432 ASSERT_FALSE(env_->IsAssignableFrom(object_array_class, string_array_class));
1433
1434 // Primitive types are tested in 004-JniTest.
1435
1436 // Null as either class should fail.
1437 CheckJniAbortCatcher jni_abort_catcher;
1438 bool old_check_jni = vm_->SetCheckJniEnabled(false);
1439 EXPECT_EQ(env_->IsAssignableFrom(nullptr, string_class), JNI_FALSE);
1440 jni_abort_catcher.Check("java_class1 == null");
1441 EXPECT_EQ(env_->IsAssignableFrom(object_class, nullptr), JNI_FALSE);
1442 jni_abort_catcher.Check("java_class2 == null");
1443 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1444 EXPECT_EQ(env_->IsAssignableFrom(nullptr, string_class), JNI_FALSE);
1445 jni_abort_catcher.Check("IsAssignableFrom received NULL jclass");
1446 EXPECT_EQ(env_->IsAssignableFrom(object_class, nullptr), JNI_FALSE);
1447 jni_abort_catcher.Check("IsAssignableFrom received NULL jclass");
1448 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
1449 }
1450
TEST_F(JniInternalTest,GetObjectRefType)1451 TEST_F(JniInternalTest, GetObjectRefType) {
1452 jclass local = env_->FindClass("java/lang/Object");
1453 ASSERT_TRUE(local != nullptr);
1454 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local));
1455
1456 jobject global = env_->NewGlobalRef(local);
1457 EXPECT_EQ(JNIGlobalRefType, env_->GetObjectRefType(global));
1458
1459 jweak weak_global = env_->NewWeakGlobalRef(local);
1460 EXPECT_EQ(JNIWeakGlobalRefType, env_->GetObjectRefType(weak_global));
1461
1462 {
1463 CheckJniAbortCatcher jni_abort_catcher;
1464 jobject invalid = reinterpret_cast<jobject>(this);
1465 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid));
1466 jni_abort_catcher.Check("use of invalid jobject");
1467 }
1468
1469 // TODO: invoke a native method and test that its arguments are considered local references.
1470
1471 // Null as pointer should not fail and return invalid-ref. b/18820997
1472 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(nullptr));
1473
1474 // TODO: Null as reference should return the original type.
1475 // This requires running a GC so a non-null object gets freed.
1476 }
1477
TEST_F(JniInternalTest,StaleWeakGlobal)1478 TEST_F(JniInternalTest, StaleWeakGlobal) {
1479 jclass java_lang_Class = env_->FindClass("java/lang/Class");
1480 ASSERT_NE(java_lang_Class, nullptr);
1481 jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, nullptr);
1482 ASSERT_NE(local_ref, nullptr);
1483 jweak weak_global = env_->NewWeakGlobalRef(local_ref);
1484 ASSERT_NE(weak_global, nullptr);
1485 env_->DeleteLocalRef(local_ref);
1486 // GC should clear the weak global.
1487 Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false);
1488 jobject new_global_ref = env_->NewGlobalRef(weak_global);
1489 EXPECT_EQ(new_global_ref, nullptr);
1490 jobject new_local_ref = env_->NewLocalRef(weak_global);
1491 EXPECT_EQ(new_local_ref, nullptr);
1492 }
1493
TEST_F(JniInternalTest,NewStringUTF)1494 TEST_F(JniInternalTest, NewStringUTF) {
1495 EXPECT_EQ(env_->NewStringUTF(nullptr), nullptr);
1496 jstring s;
1497
1498 s = env_->NewStringUTF("");
1499 EXPECT_NE(s, nullptr);
1500 EXPECT_EQ(0, env_->GetStringLength(s));
1501 EXPECT_EQ(0, env_->GetStringUTFLength(s));
1502 s = env_->NewStringUTF("hello");
1503 EXPECT_NE(s, nullptr);
1504 EXPECT_EQ(5, env_->GetStringLength(s));
1505 EXPECT_EQ(5, env_->GetStringUTFLength(s));
1506
1507 // Encoded surrogate pair.
1508 s = env_->NewStringUTF("\xed\xa0\x81\xed\xb0\x80");
1509 EXPECT_NE(s, nullptr);
1510 EXPECT_EQ(2, env_->GetStringLength(s));
1511
1512 // The surrogate pair gets encoded into a 4 byte UTF sequence..
1513 EXPECT_EQ(4, env_->GetStringUTFLength(s));
1514 const char* chars = env_->GetStringUTFChars(s, nullptr);
1515 EXPECT_STREQ("\xf0\x90\x90\x80", chars);
1516 env_->ReleaseStringUTFChars(s, chars);
1517
1518 // .. but is stored as is in the utf-16 representation.
1519 const jchar* jchars = env_->GetStringChars(s, nullptr);
1520 EXPECT_EQ(0xd801, jchars[0]);
1521 EXPECT_EQ(0xdc00, jchars[1]);
1522 env_->ReleaseStringChars(s, jchars);
1523
1524 // 4 byte UTF sequence appended to an encoded surrogate pair.
1525 s = env_->NewStringUTF("\xed\xa0\x81\xed\xb0\x80 \xf0\x9f\x8f\xa0");
1526 EXPECT_NE(s, nullptr);
1527
1528 // The 4 byte sequence {0xf0, 0x9f, 0x8f, 0xa0} is converted into a surrogate
1529 // pair {0xd83c, 0xdfe0}.
1530 EXPECT_EQ(5, env_->GetStringLength(s));
1531 jchars = env_->GetStringChars(s, nullptr);
1532 // The first surrogate pair, encoded as such in the input.
1533 EXPECT_EQ(0xd801, jchars[0]);
1534 EXPECT_EQ(0xdc00, jchars[1]);
1535 // The second surrogate pair, from the 4 byte UTF sequence in the input.
1536 EXPECT_EQ(0xd83c, jchars[3]);
1537 EXPECT_EQ(0xdfe0, jchars[4]);
1538 env_->ReleaseStringChars(s, jchars);
1539
1540 EXPECT_EQ(9, env_->GetStringUTFLength(s));
1541 chars = env_->GetStringUTFChars(s, nullptr);
1542 EXPECT_STREQ("\xf0\x90\x90\x80 \xf0\x9f\x8f\xa0", chars);
1543 env_->ReleaseStringUTFChars(s, chars);
1544
1545 // A string with 1, 2, 3 and 4 byte UTF sequences with spaces
1546 // between them
1547 s = env_->NewStringUTF("\x24 \xc2\xa2 \xe2\x82\xac \xf0\x9f\x8f\xa0");
1548 EXPECT_NE(s, nullptr);
1549 EXPECT_EQ(8, env_->GetStringLength(s));
1550 EXPECT_EQ(13, env_->GetStringUTFLength(s));
1551 }
1552
TEST_F(JniInternalTest,NewString)1553 TEST_F(JniInternalTest, NewString) {
1554 jchar chars[] = { 'h', 'i' };
1555 jstring s;
1556 s = env_->NewString(chars, 0);
1557 EXPECT_NE(s, nullptr);
1558 EXPECT_EQ(0, env_->GetStringLength(s));
1559 EXPECT_EQ(0, env_->GetStringUTFLength(s));
1560 s = env_->NewString(chars, 2);
1561 EXPECT_NE(s, nullptr);
1562 EXPECT_EQ(2, env_->GetStringLength(s));
1563 EXPECT_EQ(2, env_->GetStringUTFLength(s));
1564
1565 // TODO: check some non-ASCII strings.
1566 }
1567
TEST_F(JniInternalTest,NewStringNullCharsZeroLength)1568 TEST_F(JniInternalTest, NewStringNullCharsZeroLength) {
1569 jstring s = env_->NewString(nullptr, 0);
1570 EXPECT_NE(s, nullptr);
1571 EXPECT_EQ(0, env_->GetStringLength(s));
1572 }
1573
TEST_F(JniInternalTest,NewStringNullCharsNonzeroLength)1574 TEST_F(JniInternalTest, NewStringNullCharsNonzeroLength) {
1575 CheckJniAbortCatcher jni_abort_catcher;
1576 env_->NewString(nullptr, 1);
1577 jni_abort_catcher.Check("chars == null && char_count > 0");
1578 }
1579
TEST_F(JniInternalTest,NewStringNegativeLength)1580 TEST_F(JniInternalTest, NewStringNegativeLength) {
1581 CheckJniAbortCatcher jni_abort_catcher;
1582 bool old_check_jni = vm_->SetCheckJniEnabled(false);
1583 env_->NewString(nullptr, -1);
1584 jni_abort_catcher.Check("char_count < 0: -1");
1585 env_->NewString(nullptr, std::numeric_limits<jint>::min());
1586 jni_abort_catcher.Check("char_count < 0: -2147483648");
1587 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1588 env_->NewString(nullptr, -1);
1589 jni_abort_catcher.Check("negative jsize: -1");
1590 env_->NewString(nullptr, std::numeric_limits<jint>::min());
1591 jni_abort_catcher.Check("negative jsize: -2147483648");
1592 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
1593 }
1594
TEST_F(JniInternalTest,GetStringLength_GetStringUTFLength)1595 TEST_F(JniInternalTest, GetStringLength_GetStringUTFLength) {
1596 // Already tested in the NewString/NewStringUTF tests.
1597 }
1598
TEST_F(JniInternalTest,GetStringRegion_GetStringUTFRegion)1599 TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) {
1600 jstring s = env_->NewStringUTF("hello");
1601 ASSERT_TRUE(s != nullptr);
1602
1603 env_->GetStringRegion(s, -1, 0, nullptr);
1604 ExpectException(sioobe_);
1605 env_->GetStringRegion(s, 0, -1, nullptr);
1606 ExpectException(sioobe_);
1607 env_->GetStringRegion(s, 0, 10, nullptr);
1608 ExpectException(sioobe_);
1609 env_->GetStringRegion(s, 10, 1, nullptr);
1610 ExpectException(sioobe_);
1611 // Regression test against integer overflow in range check.
1612 env_->GetStringRegion(s, 0x7fffffff, 0x7fffffff, nullptr);
1613 ExpectException(sioobe_);
1614
1615 jchar chars[4] = { 'x', 'x', 'x', 'x' };
1616 env_->GetStringRegion(s, 1, 2, &chars[1]);
1617 EXPECT_EQ('x', chars[0]);
1618 EXPECT_EQ('e', chars[1]);
1619 EXPECT_EQ('l', chars[2]);
1620 EXPECT_EQ('x', chars[3]);
1621
1622 // It's okay for the buffer to be null as long as the length is 0.
1623 env_->GetStringRegion(s, 2, 0, nullptr);
1624 // Even if the offset is invalid...
1625 env_->GetStringRegion(s, 123, 0, nullptr);
1626 ExpectException(sioobe_);
1627
1628 env_->GetStringUTFRegion(s, -1, 0, nullptr);
1629 ExpectException(sioobe_);
1630 env_->GetStringUTFRegion(s, 0, -1, nullptr);
1631 ExpectException(sioobe_);
1632 env_->GetStringUTFRegion(s, 0, 10, nullptr);
1633 ExpectException(sioobe_);
1634 env_->GetStringUTFRegion(s, 10, 1, nullptr);
1635 ExpectException(sioobe_);
1636 // Regression test against integer overflow in range check.
1637 env_->GetStringUTFRegion(s, 0x7fffffff, 0x7fffffff, nullptr);
1638 ExpectException(sioobe_);
1639
1640 char bytes[4] = { 'x', 'x', 'x', 'x' };
1641 env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
1642 EXPECT_EQ('x', bytes[0]);
1643 EXPECT_EQ('e', bytes[1]);
1644 EXPECT_EQ('l', bytes[2]);
1645 EXPECT_EQ('x', bytes[3]);
1646
1647 // It's okay for the buffer to be null as long as the length is 0.
1648 env_->GetStringUTFRegion(s, 2, 0, nullptr);
1649 // Even if the offset is invalid...
1650 env_->GetStringUTFRegion(s, 123, 0, nullptr);
1651 ExpectException(sioobe_);
1652 }
1653
TEST_F(JniInternalTest,GetStringUTFChars_ReleaseStringUTFChars)1654 TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
1655 // Passing in a null jstring is ignored normally, but caught by -Xcheck:jni.
1656 bool old_check_jni = vm_->SetCheckJniEnabled(false);
1657 {
1658 CheckJniAbortCatcher check_jni_abort_catcher;
1659 EXPECT_EQ(env_->GetStringUTFChars(nullptr, nullptr), nullptr);
1660 }
1661 {
1662 CheckJniAbortCatcher check_jni_abort_catcher;
1663 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1664 EXPECT_EQ(env_->GetStringUTFChars(nullptr, nullptr), nullptr);
1665 check_jni_abort_catcher.Check("GetStringUTFChars received NULL jstring");
1666 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
1667 }
1668
1669 jstring s = env_->NewStringUTF("hello");
1670 ASSERT_TRUE(s != nullptr);
1671
1672 const char* utf = env_->GetStringUTFChars(s, nullptr);
1673 EXPECT_STREQ("hello", utf);
1674 env_->ReleaseStringUTFChars(s, utf);
1675
1676 jboolean is_copy = JNI_FALSE;
1677 utf = env_->GetStringUTFChars(s, &is_copy);
1678 EXPECT_EQ(JNI_TRUE, is_copy);
1679 EXPECT_STREQ("hello", utf);
1680 env_->ReleaseStringUTFChars(s, utf);
1681 }
1682
TEST_F(JniInternalTest,GetStringChars_ReleaseStringChars)1683 TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
1684 jstring s = env_->NewStringUTF("hello");
1685 ScopedObjectAccess soa(env_);
1686 ObjPtr<mirror::String> s_m = soa.Decode<mirror::String>(s);
1687 ASSERT_TRUE(s != nullptr);
1688
1689 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
1690 const jchar* chars = env_->GetStringChars(s, nullptr);
1691 EXPECT_EQ(expected[0], chars[0]);
1692 EXPECT_EQ(expected[1], chars[1]);
1693 EXPECT_EQ(expected[2], chars[2]);
1694 EXPECT_EQ(expected[3], chars[3]);
1695 EXPECT_EQ(expected[4], chars[4]);
1696 env_->ReleaseStringChars(s, chars);
1697
1698 jboolean is_copy = JNI_FALSE;
1699 chars = env_->GetStringChars(s, &is_copy);
1700 if (Runtime::Current()->GetHeap()->IsMovableObject(s_m)) {
1701 EXPECT_EQ(JNI_TRUE, is_copy);
1702 } else {
1703 EXPECT_EQ(JNI_FALSE, is_copy);
1704 }
1705 EXPECT_EQ(expected[0], chars[0]);
1706 EXPECT_EQ(expected[1], chars[1]);
1707 EXPECT_EQ(expected[2], chars[2]);
1708 EXPECT_EQ(expected[3], chars[3]);
1709 EXPECT_EQ(expected[4], chars[4]);
1710 env_->ReleaseStringChars(s, chars);
1711 }
1712
TEST_F(JniInternalTest,GetStringCritical_ReleaseStringCritical)1713 TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
1714 jstring s = env_->NewStringUTF("hello");
1715 ASSERT_TRUE(s != nullptr);
1716
1717 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
1718 const jchar* chars = env_->GetStringCritical(s, nullptr);
1719 EXPECT_EQ(expected[0], chars[0]);
1720 EXPECT_EQ(expected[1], chars[1]);
1721 EXPECT_EQ(expected[2], chars[2]);
1722 EXPECT_EQ(expected[3], chars[3]);
1723 EXPECT_EQ(expected[4], chars[4]);
1724 env_->ReleaseStringCritical(s, chars);
1725
1726 jboolean is_copy = JNI_TRUE;
1727 chars = env_->GetStringCritical(s, &is_copy);
1728 if (mirror::kUseStringCompression) {
1729 // is_copy has to be JNI_TRUE because "hello" is all-ASCII
1730 EXPECT_EQ(JNI_TRUE, is_copy);
1731 } else {
1732 EXPECT_EQ(JNI_FALSE, is_copy);
1733 }
1734 EXPECT_EQ(expected[0], chars[0]);
1735 EXPECT_EQ(expected[1], chars[1]);
1736 EXPECT_EQ(expected[2], chars[2]);
1737 EXPECT_EQ(expected[3], chars[3]);
1738 EXPECT_EQ(expected[4], chars[4]);
1739 env_->ReleaseStringCritical(s, chars);
1740
1741 if (mirror::kUseStringCompression) {
1742 // is_copy has to be JNI_FALSE because "\xed\xa0\x81\xed\xb0\x80" is incompressible
1743 jboolean is_copy_16 = JNI_TRUE;
1744 jstring s_16 = env_->NewStringUTF("\xed\xa0\x81\xed\xb0\x80");
1745 chars = env_->GetStringCritical(s_16, &is_copy_16);
1746 EXPECT_EQ(2, env_->GetStringLength(s_16));
1747 EXPECT_EQ(4, env_->GetStringUTFLength(s_16));
1748 env_->ReleaseStringCritical(s_16, chars);
1749 }
1750 }
1751
TEST_F(JniInternalTest,GetObjectArrayElement_SetObjectArrayElement)1752 TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
1753 jclass java_lang_Class = env_->FindClass("java/lang/Class");
1754 ASSERT_TRUE(java_lang_Class != nullptr);
1755
1756 jobjectArray array = env_->NewObjectArray(1, java_lang_Class, nullptr);
1757 EXPECT_NE(array, nullptr);
1758 EXPECT_EQ(env_->GetObjectArrayElement(array, 0), nullptr);
1759 env_->SetObjectArrayElement(array, 0, java_lang_Class);
1760 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class));
1761
1762 // ArrayIndexOutOfBounds for negative index.
1763 env_->SetObjectArrayElement(array, -1, java_lang_Class);
1764 ExpectException(aioobe_);
1765
1766 // ArrayIndexOutOfBounds for too-large index.
1767 env_->SetObjectArrayElement(array, 1, java_lang_Class);
1768 ExpectException(aioobe_);
1769
1770 // ArrayStoreException thrown for bad types.
1771 env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!"));
1772 ExpectException(ase_);
1773
1774 // Null as array should fail.
1775 CheckJniAbortCatcher jni_abort_catcher;
1776 bool old_check_jni = vm_->SetCheckJniEnabled(false);
1777 EXPECT_EQ(nullptr, env_->GetObjectArrayElement(nullptr, 0));
1778 jni_abort_catcher.Check("java_array == null");
1779 env_->SetObjectArrayElement(nullptr, 0, nullptr);
1780 jni_abort_catcher.Check("java_array == null");
1781 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1782 EXPECT_EQ(nullptr, env_->GetObjectArrayElement(nullptr, 0));
1783 jni_abort_catcher.Check("jarray was NULL");
1784 env_->SetObjectArrayElement(nullptr, 0, nullptr);
1785 jni_abort_catcher.Check("jarray was NULL");
1786 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
1787 }
1788
1789 #define EXPECT_STATIC_PRIMITIVE_FIELD(expect_eq, type, field_name, sig, value1, value2) \
1790 do { \
1791 jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
1792 EXPECT_NE(fid, nullptr); \
1793 env_->SetStatic ## type ## Field(c, fid, value1); \
1794 expect_eq(value1, env_->GetStatic ## type ## Field(c, fid)); \
1795 env_->SetStatic ## type ## Field(c, fid, value2); \
1796 expect_eq(value2, env_->GetStatic ## type ## Field(c, fid)); \
1797 \
1798 bool old_check_jni = vm_->SetCheckJniEnabled(false); \
1799 { \
1800 CheckJniAbortCatcher jni_abort_catcher; \
1801 env_->GetStatic ## type ## Field(nullptr, fid); \
1802 env_->SetStatic ## type ## Field(nullptr, fid, value1); \
1803 } \
1804 CheckJniAbortCatcher jni_abort_catcher; \
1805 env_->GetStatic ## type ## Field(c, nullptr); \
1806 jni_abort_catcher.Check("fid == null"); \
1807 env_->SetStatic ## type ## Field(c, nullptr, value1); \
1808 jni_abort_catcher.Check("fid == null"); \
1809 \
1810 EXPECT_FALSE(vm_->SetCheckJniEnabled(true)); \
1811 env_->GetStatic ## type ## Field(nullptr, fid); \
1812 jni_abort_catcher.Check("received NULL jclass"); \
1813 env_->SetStatic ## type ## Field(nullptr, fid, value1); \
1814 jni_abort_catcher.Check("received NULL jclass"); \
1815 env_->GetStatic ## type ## Field(c, nullptr); \
1816 jni_abort_catcher.Check("jfieldID was NULL"); \
1817 env_->SetStatic ## type ## Field(c, nullptr, value1); \
1818 jni_abort_catcher.Check("jfieldID was NULL"); \
1819 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni)); \
1820 } while (false)
1821
1822 #define EXPECT_PRIMITIVE_FIELD(expect_eq, instance, type, field_name, sig, value1, value2) \
1823 do { \
1824 jfieldID fid = env_->GetFieldID(c, field_name, sig); \
1825 EXPECT_NE(fid, nullptr); \
1826 env_->Set ## type ## Field(instance, fid, value1); \
1827 expect_eq(value1, env_->Get ## type ## Field(instance, fid)); \
1828 env_->Set ## type ## Field(instance, fid, value2); \
1829 expect_eq(value2, env_->Get ## type ## Field(instance, fid)); \
1830 \
1831 bool old_check_jni = vm_->SetCheckJniEnabled(false); \
1832 CheckJniAbortCatcher jni_abort_catcher; \
1833 env_->Get ## type ## Field(nullptr, fid); \
1834 jni_abort_catcher.Check("obj == null"); \
1835 env_->Set ## type ## Field(nullptr, fid, value1); \
1836 jni_abort_catcher.Check("obj == null"); \
1837 env_->Get ## type ## Field(instance, nullptr); \
1838 jni_abort_catcher.Check("fid == null"); \
1839 env_->Set ## type ## Field(instance, nullptr, value1); \
1840 jni_abort_catcher.Check("fid == null"); \
1841 EXPECT_FALSE(vm_->SetCheckJniEnabled(true)); \
1842 env_->Get ## type ## Field(nullptr, fid); \
1843 jni_abort_catcher.Check("field operation on NULL object:"); \
1844 env_->Set ## type ## Field(nullptr, fid, value1); \
1845 jni_abort_catcher.Check("field operation on NULL object:"); \
1846 env_->Get ## type ## Field(instance, nullptr); \
1847 jni_abort_catcher.Check("jfieldID was NULL"); \
1848 env_->Set ## type ## Field(instance, nullptr, value1); \
1849 jni_abort_catcher.Check("jfieldID was NULL"); \
1850 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni)); \
1851 } while (false)
1852
1853 #define TEST_PRIMITIVE_FIELD_FOR_CLASS(cname) \
1854 do { \
1855 Thread::Current()->TransitionFromSuspendedToRunnable(); \
1856 LoadDex("AllFields"); \
1857 bool started = runtime_->Start(); \
1858 ASSERT_TRUE(started); \
1859 jclass c = env_->FindClass(cname); \
1860 ASSERT_NE(c, nullptr); \
1861 jobject o = env_->AllocObject(c); \
1862 ASSERT_NE(o, nullptr); \
1863 \
1864 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Boolean, "sZ", "Z", JNI_TRUE, JNI_FALSE); \
1865 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Byte, "sB", "B", 1, 2); \
1866 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Char, "sC", "C", 'a', 'b'); \
1867 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_DOUBLE_EQ, Double, "sD", "D", 1.0, 2.0); \
1868 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_FLOAT_EQ, Float, "sF", "F", 1.0, 2.0); \
1869 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Int, "sI", "I", 1, 2); \
1870 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Long, "sJ", "J", 1, 2); \
1871 EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Short, "sS", "S", 1, 2); \
1872 \
1873 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Boolean, "iZ", "Z", JNI_TRUE, JNI_FALSE); \
1874 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Byte, "iB", "B", 1, 2); \
1875 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Char, "iC", "C", 'a', 'b'); \
1876 EXPECT_PRIMITIVE_FIELD(EXPECT_DOUBLE_EQ, o, Double, "iD", "D", 1.0, 2.0); \
1877 EXPECT_PRIMITIVE_FIELD(EXPECT_FLOAT_EQ, o, Float, "iF", "F", 1.0, 2.0); \
1878 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Int, "iI", "I", 1, 2); \
1879 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Long, "iJ", "J", 1, 2); \
1880 EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Short, "iS", "S", 1, 2); \
1881 } while (false)
1882
TEST_F(JniInternalTest,GetPrimitiveField_SetPrimitiveField)1883 TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
1884 TEST_PRIMITIVE_FIELD_FOR_CLASS("AllFields");
1885 }
1886
TEST_F(JniInternalTest,GetPrimitiveField_SetPrimitiveField_Subclass)1887 TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField_Subclass) {
1888 TEST_PRIMITIVE_FIELD_FOR_CLASS("AllFieldsSub");
1889 }
1890
1891 #define EXPECT_UNRELATED_FIELD_FAILURE(type, field_name, sig, value1) \
1892 do { \
1893 jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
1894 EXPECT_NE(fid, nullptr); \
1895 CheckJniAbortCatcher jni_abort_catcher; \
1896 env_->Get ## type ## Field(uc, fid); \
1897 jni_abort_catcher.Check("not valid for an object of class"); \
1898 env_->Set ## type ## Field(uc, fid, value1); \
1899 jni_abort_catcher.Check("not valid for an object of class"); \
1900 } while (false)
1901
TEST_F(JniInternalTest,GetField_SetField_unrelated)1902 TEST_F(JniInternalTest, GetField_SetField_unrelated) {
1903 Thread::Current()->TransitionFromSuspendedToRunnable();
1904 LoadDex("AllFields");
1905 bool started = runtime_->Start();
1906 ASSERT_TRUE(started);
1907 jclass c = env_->FindClass("AllFields");
1908 ASSERT_NE(c, nullptr);
1909 jclass uc = env_->FindClass("AllFieldsUnrelated");
1910 ASSERT_NE(uc, nullptr);
1911 bool old_check_jni = vm_->SetCheckJniEnabled(true);
1912 EXPECT_UNRELATED_FIELD_FAILURE(Boolean, "sZ", "Z", JNI_TRUE);
1913 EXPECT_UNRELATED_FIELD_FAILURE(Byte, "sB", "B", 1);
1914 EXPECT_UNRELATED_FIELD_FAILURE(Char, "sC", "C", 'a');
1915 EXPECT_UNRELATED_FIELD_FAILURE(Double, "sD", "D", 1.0);
1916 EXPECT_UNRELATED_FIELD_FAILURE(Float, "sF", "F", 1.0);
1917 EXPECT_UNRELATED_FIELD_FAILURE(Int, "sI", "I", 1);
1918 EXPECT_UNRELATED_FIELD_FAILURE(Long, "sJ", "J", 1);
1919 EXPECT_UNRELATED_FIELD_FAILURE(Short, "sS", "S", 1);
1920 EXPECT_UNRELATED_FIELD_FAILURE(Object, "sObject", "Ljava/lang/Object;", c);
1921 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
1922 }
1923
1924 #define TEST_OBJECT_FIELD_FOR_CLASS(cname) \
1925 do { \
1926 Thread::Current()->TransitionFromSuspendedToRunnable(); \
1927 LoadDex("AllFields"); \
1928 runtime_->Start(); \
1929 \
1930 jclass c = env_->FindClass(cname); \
1931 ASSERT_NE(c, nullptr); \
1932 jobject o = env_->AllocObject(c); \
1933 ASSERT_NE(o, nullptr); \
1934 \
1935 jstring s1 = env_->NewStringUTF("hello"); \
1936 ASSERT_NE(s1, nullptr); \
1937 jstring s2 = env_->NewStringUTF("world"); \
1938 ASSERT_NE(s2, nullptr); \
1939 \
1940 jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;"); \
1941 ASSERT_NE(s_fid, nullptr); \
1942 jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;"); \
1943 ASSERT_NE(i_fid, nullptr); \
1944 \
1945 env_->SetStaticObjectField(c, s_fid, s1); \
1946 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid))); \
1947 env_->SetStaticObjectField(c, s_fid, s2); \
1948 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetStaticObjectField(c, s_fid))); \
1949 \
1950 env_->SetObjectField(o, i_fid, s1); \
1951 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetObjectField(o, i_fid))); \
1952 env_->SetObjectField(o, i_fid, s2); \
1953 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid))); \
1954 } while (false)
1955
TEST_F(JniInternalTest,GetObjectField_SetObjectField)1956 TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
1957 TEST_OBJECT_FIELD_FOR_CLASS("AllFields");
1958 }
1959
TEST_F(JniInternalTest,GetObjectField_SetObjectField_subclass)1960 TEST_F(JniInternalTest, GetObjectField_SetObjectField_subclass) {
1961 TEST_OBJECT_FIELD_FOR_CLASS("AllFieldsSub");
1962 }
1963
TEST_F(JniInternalTest,NewLocalRef_nullptr)1964 TEST_F(JniInternalTest, NewLocalRef_nullptr) {
1965 EXPECT_EQ(env_->NewLocalRef(nullptr), nullptr);
1966 }
1967
TEST_F(JniInternalTest,NewLocalRef)1968 TEST_F(JniInternalTest, NewLocalRef) {
1969 jstring s = env_->NewStringUTF("");
1970 ASSERT_NE(s, nullptr);
1971 jobject o = env_->NewLocalRef(s);
1972 EXPECT_NE(o, nullptr);
1973 EXPECT_NE(o, s);
1974
1975 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o));
1976 }
1977
TEST_F(JniInternalTest,DeleteLocalRef_nullptr)1978 TEST_F(JniInternalTest, DeleteLocalRef_nullptr) {
1979 env_->DeleteLocalRef(nullptr);
1980 }
1981
TEST_F(JniInternalTest,DeleteLocalRef)1982 TEST_F(JniInternalTest, DeleteLocalRef) {
1983 // This tests leads to warnings and errors in the log.
1984 ScopedLogSeverity sls(LogSeverity::FATAL);
1985
1986 jstring s = env_->NewStringUTF("");
1987 ASSERT_NE(s, nullptr);
1988 env_->DeleteLocalRef(s);
1989
1990 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
1991 {
1992 bool old_check_jni = vm_->SetCheckJniEnabled(false);
1993 {
1994 CheckJniAbortCatcher check_jni_abort_catcher;
1995 env_->DeleteLocalRef(s);
1996 }
1997 CheckJniAbortCatcher check_jni_abort_catcher;
1998 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
1999 env_->DeleteLocalRef(s);
2000 std::string expected(StringPrintf("use of deleted local reference %p", s));
2001 check_jni_abort_catcher.Check(expected.c_str());
2002 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
2003 }
2004
2005 s = env_->NewStringUTF("");
2006 ASSERT_NE(s, nullptr);
2007 jobject o = env_->NewLocalRef(s);
2008 ASSERT_NE(o, nullptr);
2009
2010 env_->DeleteLocalRef(s);
2011 env_->DeleteLocalRef(o);
2012 }
2013
TEST_F(JniInternalTest,PushLocalFrame_10395422)2014 TEST_F(JniInternalTest, PushLocalFrame_10395422) {
2015 // The JNI specification is ambiguous about whether the given capacity is to be interpreted as a
2016 // maximum or as a minimum, but it seems like it's supposed to be a minimum, and that's how
2017 // Android historically treated it, and it's how the RI treats it. It's also the more useful
2018 // interpretation!
2019 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(0));
2020 env_->PopLocalFrame(nullptr);
2021
2022 // The following two tests will print errors to the log.
2023 ScopedLogSeverity sls(LogSeverity::FATAL);
2024
2025 // Negative capacities are not allowed.
2026 ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1));
2027 }
2028
TEST_F(JniInternalTest,PushLocalFrame_PopLocalFrame)2029 TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) {
2030 // This tests leads to errors in the log.
2031 ScopedLogSeverity sls(LogSeverity::FATAL);
2032
2033 jobject original = env_->NewStringUTF("");
2034 ASSERT_NE(original, nullptr);
2035
2036 jobject outer;
2037 jobject inner1, inner2;
2038 ScopedObjectAccess soa(env_);
2039 {
2040 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
2041 outer = env_->NewLocalRef(original);
2042
2043 {
2044 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
2045 inner1 = env_->NewLocalRef(outer);
2046 inner2 = env_->NewStringUTF("survivor");
2047 EXPECT_NE(env_->PopLocalFrame(inner2), nullptr);
2048 }
2049
2050 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
2051 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(outer));
2052 {
2053 CheckJniAbortCatcher check_jni_abort_catcher;
2054 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
2055 check_jni_abort_catcher.Check("use of deleted local reference");
2056 }
2057
2058 // Our local reference for the survivor is invalid because the survivor
2059 // gets a new local reference...
2060 {
2061 CheckJniAbortCatcher check_jni_abort_catcher;
2062 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
2063 check_jni_abort_catcher.Check("use of deleted local reference");
2064 }
2065
2066 EXPECT_EQ(env_->PopLocalFrame(nullptr), nullptr);
2067 }
2068 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
2069 CheckJniAbortCatcher check_jni_abort_catcher;
2070 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
2071 check_jni_abort_catcher.Check("use of deleted local reference");
2072 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
2073 check_jni_abort_catcher.Check("use of deleted local reference");
2074 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
2075 check_jni_abort_catcher.Check("use of deleted local reference");
2076 }
2077
TEST_F(JniInternalTest,PushLocalFrame_LimitAndOverflow)2078 TEST_F(JniInternalTest, PushLocalFrame_LimitAndOverflow) {
2079 // Try a very large value that should fail.
2080 ASSERT_NE(JNI_OK, env_->PushLocalFrame(std::numeric_limits<jint>::max()));
2081 ASSERT_TRUE(env_->ExceptionCheck());
2082 env_->ExceptionClear();
2083
2084 // On 32-bit, also check for some overflow conditions.
2085 #ifndef __LP64__
2086 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(10));
2087 ASSERT_NE(JNI_OK, env_->PushLocalFrame(std::numeric_limits<jint>::max() - 10));
2088 ASSERT_TRUE(env_->ExceptionCheck());
2089 env_->ExceptionClear();
2090 EXPECT_EQ(env_->PopLocalFrame(nullptr), nullptr);
2091 #endif
2092 }
2093
TEST_F(JniInternalTest,PushLocalFrame_b62223672)2094 TEST_F(JniInternalTest, PushLocalFrame_b62223672) {
2095 // The 512 entry limit has been lifted, try a larger value.
2096 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(1024));
2097 EXPECT_EQ(env_->PopLocalFrame(nullptr), nullptr);
2098 }
2099
TEST_F(JniInternalTest,NewGlobalRef_nullptr)2100 TEST_F(JniInternalTest, NewGlobalRef_nullptr) {
2101 EXPECT_EQ(env_->NewGlobalRef(nullptr), nullptr);
2102 }
2103
TEST_F(JniInternalTest,NewGlobalRef)2104 TEST_F(JniInternalTest, NewGlobalRef) {
2105 jstring s = env_->NewStringUTF("");
2106 ASSERT_NE(s, nullptr);
2107 jobject o = env_->NewGlobalRef(s);
2108 EXPECT_NE(o, nullptr);
2109 EXPECT_NE(o, s);
2110
2111 EXPECT_EQ(env_->GetObjectRefType(o), JNIGlobalRefType);
2112 }
2113
TEST_F(JniInternalTest,DeleteGlobalRef_nullptr)2114 TEST_F(JniInternalTest, DeleteGlobalRef_nullptr) {
2115 env_->DeleteGlobalRef(nullptr);
2116 }
2117
TEST_F(JniInternalTest,DeleteGlobalRef)2118 TEST_F(JniInternalTest, DeleteGlobalRef) {
2119 // This tests leads to warnings and errors in the log.
2120 ScopedLogSeverity sls(LogSeverity::FATAL);
2121
2122 jstring s = env_->NewStringUTF("");
2123 ASSERT_NE(s, nullptr);
2124
2125 jobject o = env_->NewGlobalRef(s);
2126 ASSERT_NE(o, nullptr);
2127 env_->DeleteGlobalRef(o);
2128
2129 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
2130 {
2131 bool old_check_jni = vm_->SetCheckJniEnabled(false);
2132 {
2133 CheckJniAbortCatcher check_jni_abort_catcher;
2134 env_->DeleteGlobalRef(o);
2135 }
2136 CheckJniAbortCatcher check_jni_abort_catcher;
2137 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
2138 env_->DeleteGlobalRef(o);
2139 std::string expected(StringPrintf("use of deleted global reference %p", o));
2140 check_jni_abort_catcher.Check(expected.c_str());
2141 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
2142 }
2143
2144 jobject o1 = env_->NewGlobalRef(s);
2145 ASSERT_NE(o1, nullptr);
2146 jobject o2 = env_->NewGlobalRef(s);
2147 ASSERT_NE(o2, nullptr);
2148
2149 env_->DeleteGlobalRef(o1);
2150 env_->DeleteGlobalRef(o2);
2151 }
2152
TEST_F(JniInternalTest,NewWeakGlobalRef_nullptr)2153 TEST_F(JniInternalTest, NewWeakGlobalRef_nullptr) {
2154 EXPECT_EQ(env_->NewWeakGlobalRef(nullptr), nullptr);
2155 }
2156
TEST_F(JniInternalTest,NewWeakGlobalRef)2157 TEST_F(JniInternalTest, NewWeakGlobalRef) {
2158 jstring s = env_->NewStringUTF("");
2159 ASSERT_NE(s, nullptr);
2160 jobject o = env_->NewWeakGlobalRef(s);
2161 EXPECT_NE(o, nullptr);
2162 EXPECT_NE(o, s);
2163
2164 EXPECT_EQ(env_->GetObjectRefType(o), JNIWeakGlobalRefType);
2165 }
2166
TEST_F(JniInternalTest,DeleteWeakGlobalRef_nullptr)2167 TEST_F(JniInternalTest, DeleteWeakGlobalRef_nullptr) {
2168 env_->DeleteWeakGlobalRef(nullptr);
2169 }
2170
TEST_F(JniInternalTest,DeleteWeakGlobalRef)2171 TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
2172 // This tests leads to warnings and errors in the log.
2173 ScopedLogSeverity sls(LogSeverity::FATAL);
2174
2175 jstring s = env_->NewStringUTF("");
2176 ASSERT_NE(s, nullptr);
2177
2178 jobject o = env_->NewWeakGlobalRef(s);
2179 ASSERT_NE(o, nullptr);
2180 env_->DeleteWeakGlobalRef(o);
2181
2182 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
2183 {
2184 bool old_check_jni = vm_->SetCheckJniEnabled(false);
2185 {
2186 CheckJniAbortCatcher check_jni_abort_catcher;
2187 env_->DeleteWeakGlobalRef(o);
2188 }
2189 CheckJniAbortCatcher check_jni_abort_catcher;
2190 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
2191 env_->DeleteWeakGlobalRef(o);
2192 std::string expected(StringPrintf("use of deleted weak global reference %p", o));
2193 check_jni_abort_catcher.Check(expected.c_str());
2194 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
2195 }
2196
2197 jobject o1 = env_->NewWeakGlobalRef(s);
2198 ASSERT_NE(o1, nullptr);
2199 jobject o2 = env_->NewWeakGlobalRef(s);
2200 ASSERT_NE(o2, nullptr);
2201
2202 env_->DeleteWeakGlobalRef(o1);
2203 env_->DeleteWeakGlobalRef(o2);
2204 }
2205
TEST_F(JniInternalTest,ExceptionDescribe)2206 TEST_F(JniInternalTest, ExceptionDescribe) {
2207 // This checks how ExceptionDescribe handles call without exception.
2208 env_->ExceptionClear();
2209 env_->ExceptionDescribe();
2210 }
2211
TEST_F(JniInternalTest,Throw)2212 TEST_F(JniInternalTest, Throw) {
2213 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
2214 ASSERT_TRUE(exception_class != nullptr);
2215 jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class));
2216 ASSERT_TRUE(exception != nullptr);
2217
2218 EXPECT_EQ(JNI_OK, env_->Throw(exception));
2219 EXPECT_TRUE(env_->ExceptionCheck());
2220 jthrowable thrown_exception = env_->ExceptionOccurred();
2221 env_->ExceptionClear();
2222 EXPECT_TRUE(env_->IsSameObject(exception, thrown_exception));
2223
2224 // Bad argument.
2225 bool old_check_jni = vm_->SetCheckJniEnabled(false);
2226 EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
2227 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
2228 CheckJniAbortCatcher check_jni_abort_catcher;
2229 EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
2230 check_jni_abort_catcher.Check("Throw received NULL jthrowable");
2231 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
2232 }
2233
TEST_F(JniInternalTest,ThrowNew)2234 TEST_F(JniInternalTest, ThrowNew) {
2235 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
2236 ASSERT_TRUE(exception_class != nullptr);
2237
2238 jthrowable thrown_exception;
2239
2240 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, "hello world"));
2241 EXPECT_TRUE(env_->ExceptionCheck());
2242 thrown_exception = env_->ExceptionOccurred();
2243 env_->ExceptionClear();
2244 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
2245
2246 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, nullptr));
2247 EXPECT_TRUE(env_->ExceptionCheck());
2248 thrown_exception = env_->ExceptionOccurred();
2249 env_->ExceptionClear();
2250 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
2251
2252 // Bad argument.
2253 bool old_check_jni = vm_->SetCheckJniEnabled(false);
2254 CheckJniAbortCatcher check_jni_abort_catcher;
2255 EXPECT_EQ(JNI_ERR, env_->ThrowNew(nullptr, nullptr));
2256 check_jni_abort_catcher.Check("c == null");
2257 EXPECT_FALSE(vm_->SetCheckJniEnabled(true));
2258 EXPECT_EQ(JNI_ERR, env_->ThrowNew(nullptr, nullptr));
2259 check_jni_abort_catcher.Check("ThrowNew received NULL jclass");
2260 EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
2261 }
2262
TEST_F(JniInternalTest,NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity)2263 TEST_F(JniInternalTest, NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity) {
2264 // Start runtime.
2265 Thread* self = Thread::Current();
2266 self->TransitionFromSuspendedToRunnable();
2267 MakeInterpreted(class_linker_->FindSystemClass(self, "Ljava/lang/Class;"));
2268 MakeInterpreted(class_linker_->FindSystemClass(self, "Ljava/lang/Object;"));
2269 MakeInterpreted(class_linker_->FindSystemClass(self, "Ljava/nio/DirectByteBuffer;"));
2270 MakeInterpreted(class_linker_->FindSystemClass(self, "Ljava/nio/Bits;"));
2271 MakeInterpreted(class_linker_->FindSystemClass(self, "Ljava/nio/MappedByteBuffer;"));
2272 MakeInterpreted(class_linker_->FindSystemClass(self, "Ljava/nio/ByteBuffer;"));
2273 MakeInterpreted(class_linker_->FindSystemClass(self, "Ljava/nio/Buffer;"));
2274 // TODO: we only load a dex file here as starting the runtime relies upon it.
2275 const char* class_name = "StaticLeafMethods";
2276 LoadDex(class_name);
2277 bool started = runtime_->Start();
2278 ASSERT_TRUE(started);
2279
2280 jclass buffer_class = env_->FindClass("java/nio/Buffer");
2281 ASSERT_NE(buffer_class, nullptr);
2282
2283 char bytes[1024];
2284 jobject direct_buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
2285 ASSERT_NE(direct_buffer, nullptr);
2286 ASSERT_TRUE(env_->IsInstanceOf(direct_buffer, buffer_class));
2287 ASSERT_EQ(env_->GetDirectBufferAddress(direct_buffer), bytes);
2288 ASSERT_EQ(env_->GetDirectBufferCapacity(direct_buffer), static_cast<jlong>(sizeof(bytes)));
2289
2290 // Check we don't crash if a nullptr is passed to field accessors.
2291 ASSERT_EQ(env_->GetDirectBufferAddress(nullptr), nullptr);
2292 ASSERT_EQ(env_->GetDirectBufferCapacity(nullptr), -1L);
2293
2294 // Check if j.n.Buffer types backed by heap memory return the invalid values described in the
2295 // RETURNS clauses of JNI spec for GetDirectBufferAddress() and GetDirectBufferCapacity().
2296 ScopedLocalRef<jclass> bb(env_, env_->FindClass("java/nio/ByteBuffer"));
2297 jmethodID bb_allocate = env_->GetStaticMethodID(bb.get(), "allocate", "(I)Ljava/nio/ByteBuffer;");
2298 jobject heap_buffer = env_->CallStaticObjectMethod(bb.get(), bb_allocate, 128);
2299 ASSERT_NE(heap_buffer, nullptr);
2300 ASSERT_EQ(env_->GetDirectBufferAddress(heap_buffer), nullptr);
2301 ASSERT_EQ(env_->GetDirectBufferCapacity(heap_buffer), -1L);
2302
2303 // Check invalid values are returned if the buffer argument has an object type is not a sub-type
2304 // of j.n.Buffer.
2305 jobject not_buffer = env_->NewStringUTF("A String");
2306 ASSERT_EQ(env_->GetDirectBufferAddress(not_buffer), nullptr);
2307 ASSERT_EQ(env_->GetDirectBufferCapacity(not_buffer), -1L);
2308
2309 {
2310 CheckJniAbortCatcher check_jni_abort_catcher;
2311 env_->NewDirectByteBuffer(bytes, static_cast<jlong>(INT_MAX) + 1);
2312 check_jni_abort_catcher.Check("in call to NewDirectByteBuffer");
2313 }
2314 }
2315
TEST_F(JniInternalTest,MonitorEnterExit)2316 TEST_F(JniInternalTest, MonitorEnterExit) {
2317 // This will print some error messages. Suppress.
2318 ScopedLogSeverity sls(LogSeverity::FATAL);
2319
2320 // Create an object to torture.
2321 jclass object_class = env_->FindClass("java/lang/Object");
2322 ASSERT_NE(object_class, nullptr);
2323 jobject object = env_->AllocObject(object_class);
2324 ASSERT_NE(object, nullptr);
2325
2326 // Expected class of exceptions
2327 jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException");
2328 ASSERT_NE(imse_class, nullptr);
2329
2330 jthrowable thrown_exception;
2331
2332 // Unlock of unowned monitor
2333 env_->MonitorExit(object);
2334 EXPECT_TRUE(env_->ExceptionCheck());
2335 thrown_exception = env_->ExceptionOccurred();
2336 env_->ExceptionClear();
2337 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
2338
2339 // Lock of unowned monitor
2340 env_->MonitorEnter(object);
2341 EXPECT_FALSE(env_->ExceptionCheck());
2342 // Regular unlock
2343 env_->MonitorExit(object);
2344 EXPECT_FALSE(env_->ExceptionCheck());
2345
2346 // Recursively lock a lot
2347 size_t max_recursive_lock = 1024;
2348 for (size_t i = 0; i < max_recursive_lock; i++) {
2349 env_->MonitorEnter(object);
2350 EXPECT_FALSE(env_->ExceptionCheck());
2351 }
2352 // Recursively unlock a lot
2353 for (size_t i = 0; i < max_recursive_lock; i++) {
2354 env_->MonitorExit(object);
2355 EXPECT_FALSE(env_->ExceptionCheck());
2356 }
2357
2358 // Unlock of unowned monitor
2359 env_->MonitorExit(object);
2360 EXPECT_TRUE(env_->ExceptionCheck());
2361 thrown_exception = env_->ExceptionOccurred();
2362 env_->ExceptionClear();
2363 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
2364
2365 // It's an error to call MonitorEnter or MonitorExit on null.
2366 {
2367 CheckJniAbortCatcher check_jni_abort_catcher;
2368 env_->MonitorEnter(nullptr);
2369 check_jni_abort_catcher.Check("in call to MonitorEnter");
2370 env_->MonitorExit(nullptr);
2371 check_jni_abort_catcher.Check("in call to MonitorExit");
2372 }
2373 }
2374
Java_MyClassNatives_foo_exit(JNIEnv * env,jobject thisObj)2375 void Java_MyClassNatives_foo_exit(JNIEnv* env, jobject thisObj) {
2376 // Release the monitor on self. This should trigger an abort.
2377 env->MonitorExit(thisObj);
2378 }
2379
TEST_F(JniInternalTest,MonitorExitLockedInDifferentCall)2380 TEST_F(JniInternalTest, MonitorExitLockedInDifferentCall) {
2381 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo_exit));
2382 ASSERT_NE(jobj_, nullptr);
2383
2384 env_->MonitorEnter(jobj_);
2385 EXPECT_FALSE(env_->ExceptionCheck());
2386
2387 CheckJniAbortCatcher check_jni_abort_catcher;
2388 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
2389 check_jni_abort_catcher.Check("Unlocking monitor that wasn't locked here");
2390 }
2391
Java_MyClassNatives_foo_enter_no_exit(JNIEnv * env,jobject thisObj)2392 void Java_MyClassNatives_foo_enter_no_exit(JNIEnv* env, jobject thisObj) {
2393 // Acquire but don't release the monitor on self. This should trigger an abort on return.
2394 env->MonitorEnter(thisObj);
2395 }
2396
TEST_F(JniInternalTest,MonitorExitNotAllUnlocked)2397 TEST_F(JniInternalTest, MonitorExitNotAllUnlocked) {
2398 SetUpForTest(false,
2399 "foo",
2400 "()V",
2401 reinterpret_cast<void*>(&Java_MyClassNatives_foo_enter_no_exit));
2402 ASSERT_NE(jobj_, nullptr);
2403
2404 CheckJniAbortCatcher check_jni_abort_catcher;
2405 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
2406 check_jni_abort_catcher.Check("Still holding a locked object on JNI end");
2407 }
2408
IsLocked(JNIEnv * env,jobject jobj)2409 static bool IsLocked(JNIEnv* env, jobject jobj) {
2410 ScopedObjectAccess soa(env);
2411 LockWord lock_word = soa.Decode<mirror::Object>(jobj)->GetLockWord(true);
2412 switch (lock_word.GetState()) {
2413 case LockWord::kHashCode:
2414 case LockWord::kUnlocked:
2415 return false;
2416 case LockWord::kThinLocked:
2417 return true;
2418 case LockWord::kFatLocked:
2419 return lock_word.FatLockMonitor()->IsLocked();
2420 default: {
2421 LOG(FATAL) << "Invalid monitor state " << lock_word.GetState();
2422 UNREACHABLE();
2423 }
2424 }
2425 }
2426
TEST_F(JniInternalTest,DetachThreadUnlockJNIMonitors)2427 TEST_F(JniInternalTest, DetachThreadUnlockJNIMonitors) {
2428 // We need to lock an object, detach, reattach, and check the locks.
2429 //
2430 // As re-attaching will create a different thread, we need to use a global
2431 // ref to keep the object around.
2432
2433 // Create an object to torture.
2434 jobject global_ref;
2435 {
2436 jclass object_class = env_->FindClass("java/lang/Object");
2437 ASSERT_NE(object_class, nullptr);
2438 jobject object = env_->AllocObject(object_class);
2439 ASSERT_NE(object, nullptr);
2440 global_ref = env_->NewGlobalRef(object);
2441 }
2442
2443 // Lock it.
2444 env_->MonitorEnter(global_ref);
2445 ASSERT_TRUE(IsLocked(env_, global_ref));
2446
2447 // Detach and re-attach.
2448 jint detach_result = vm_->DetachCurrentThread();
2449 ASSERT_EQ(detach_result, JNI_OK);
2450 jint attach_result = vm_->AttachCurrentThread(&env_, nullptr);
2451 ASSERT_EQ(attach_result, JNI_OK);
2452
2453 // Look at the global ref, check whether it's still locked.
2454 ASSERT_FALSE(IsLocked(env_, global_ref));
2455
2456 // Delete the global ref.
2457 env_->DeleteGlobalRef(global_ref);
2458 }
2459
2460 // Test the offset computation of IndirectReferenceTable offsets. b/26071368.
TEST_F(JniInternalTest,IndirectReferenceTableOffsets)2461 TEST_F(JniInternalTest, IndirectReferenceTableOffsets) {
2462 // The segment_state_ field is private, and we want to avoid friend declaration. So we'll check
2463 // by modifying memory.
2464 // The parameters don't really matter here.
2465 std::string error_msg;
2466 IndirectReferenceTable irt(5,
2467 IndirectRefKind::kGlobal,
2468 IndirectReferenceTable::ResizableCapacity::kNo,
2469 &error_msg);
2470 ASSERT_TRUE(irt.IsValid()) << error_msg;
2471 IRTSegmentState old_state = irt.GetSegmentState();
2472
2473 // Write some new state directly. We invert parts of old_state to ensure a new value.
2474 IRTSegmentState new_state;
2475 new_state.top_index = old_state.top_index ^ 0x07705005;
2476 ASSERT_NE(old_state.top_index, new_state.top_index);
2477
2478 uint8_t* base = reinterpret_cast<uint8_t*>(&irt);
2479 int32_t segment_state_offset =
2480 IndirectReferenceTable::SegmentStateOffset(sizeof(void*)).Int32Value();
2481 *reinterpret_cast<IRTSegmentState*>(base + segment_state_offset) = new_state;
2482
2483 // Read and compare.
2484 EXPECT_EQ(new_state.top_index, irt.GetSegmentState().top_index);
2485 }
2486
2487 // Test the offset computation of JNIEnvExt offsets. b/26071368.
TEST_F(JniInternalTest,JNIEnvExtOffsets)2488 TEST_F(JniInternalTest, JNIEnvExtOffsets) {
2489 EXPECT_EQ(OFFSETOF_MEMBER(JNIEnvExt, local_ref_cookie_),
2490 JNIEnvExt::LocalRefCookieOffset(sizeof(void*)).Uint32Value());
2491
2492 EXPECT_EQ(OFFSETOF_MEMBER(JNIEnvExt, self_), JNIEnvExt::SelfOffset(sizeof(void*)).Uint32Value());
2493
2494 // segment_state_ is private in the IndirectReferenceTable. So this test isn't as good as we'd
2495 // hope it to be.
2496 uint32_t segment_state_now =
2497 OFFSETOF_MEMBER(JNIEnvExt, locals_) +
2498 IndirectReferenceTable::SegmentStateOffset(sizeof(void*)).Uint32Value();
2499 uint32_t segment_state_computed = JNIEnvExt::SegmentStateOffset(sizeof(void*)).Uint32Value();
2500 EXPECT_EQ(segment_state_now, segment_state_computed);
2501 }
2502
2503 static size_t gGlobalRefCount = 0;
2504 static const JNINativeInterface* gOriginalEnv = nullptr;
2505
CountNewGlobalRef(JNIEnv * env,jobject o)2506 static jobject CountNewGlobalRef(JNIEnv* env, jobject o) {
2507 ++gGlobalRefCount;
2508 return gOriginalEnv->NewGlobalRef(env, o);
2509 }
2510
2511 // Test the table override.
TEST_F(JniInternalTest,JNIEnvExtTableOverride)2512 TEST_F(JniInternalTest, JNIEnvExtTableOverride) {
2513 JNINativeInterface env_override;
2514 memcpy(&env_override, env_->functions, sizeof(JNINativeInterface));
2515
2516 gOriginalEnv = env_->functions;
2517 env_override.NewGlobalRef = CountNewGlobalRef;
2518 gGlobalRefCount = 0;
2519
2520 jclass local = env_->FindClass("java/lang/Object");
2521 ASSERT_TRUE(local != nullptr);
2522
2523 // Set the table, add a global ref, see whether the counter increases.
2524 JNIEnvExt::SetTableOverride(&env_override);
2525
2526 jobject global = env_->NewGlobalRef(local);
2527 EXPECT_EQ(1u, gGlobalRefCount);
2528 env_->DeleteGlobalRef(global);
2529
2530 // Reset
2531 JNIEnvExt::SetTableOverride(nullptr);
2532
2533 jobject global2 = env_->NewGlobalRef(local);
2534 EXPECT_EQ(1u, gGlobalRefCount);
2535 env_->DeleteGlobalRef(global2);
2536 }
2537
TEST_F(JniInternalTest,NonAttachedThread)2538 TEST_F(JniInternalTest, NonAttachedThread) {
2539 // This tests leads to warnings and errors in the log.
2540 ScopedLogSeverity sls(LogSeverity::FATAL);
2541 CheckJniAbortCatcher check_jni_abort_catcher;
2542
2543 auto callee = [](void* env_ptr) -> void* {
2544 JNIEnv* env = reinterpret_cast<JNIEnv*>(env_ptr);
2545 env->NewStringUTF("test");
2546 return nullptr;
2547 };
2548
2549 bool old_check_jni = vm_->SetCheckJniEnabled(false);
2550 vm_->SetCheckJniEnabled(true);
2551 {
2552 pthread_t pthread;
2553 int pthread_create_result = pthread_create(&pthread,
2554 /* pthread_attr */ nullptr,
2555 callee,
2556 reinterpret_cast<void*>(env_));
2557 CHECK_EQ(pthread_create_result, 0);
2558 int pthread_join_result = pthread_join(pthread, /* thread_return */ nullptr);
2559 CHECK_EQ(pthread_join_result, 0);
2560 }
2561 vm_->SetCheckJniEnabled(old_check_jni);
2562
2563 check_jni_abort_catcher.Check("is making JNI calls without being attached");
2564 }
2565
2566 } // namespace art
2567