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 "common_compiler_test.h" 20 #include "mirror/art_method-inl.h" 21 #include "mirror/string-inl.h" 22 #include "scoped_thread_state_change.h" 23 #include "ScopedLocalRef.h" 24 25 namespace art { 26 27 // TODO: Convert to CommonRuntimeTest. Currently MakeExecutable is used. 28 class JniInternalTest : public CommonCompilerTest { 29 protected: 30 virtual void SetUp() { 31 CommonCompilerTest::SetUp(); 32 33 vm_ = Runtime::Current()->GetJavaVM(); 34 35 // Turn on -verbose:jni for the JNI tests. 36 // gLogVerbosity.jni = true; 37 38 vm_->AttachCurrentThread(&env_, nullptr); 39 40 ScopedLocalRef<jclass> aioobe(env_, 41 env_->FindClass("java/lang/ArrayIndexOutOfBoundsException")); 42 CHECK(aioobe.get() != nullptr); 43 aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get())); 44 45 ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException")); 46 CHECK(ase.get() != nullptr); 47 ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get())); 48 49 ScopedLocalRef<jclass> sioobe(env_, 50 env_->FindClass("java/lang/StringIndexOutOfBoundsException")); 51 CHECK(sioobe.get() != nullptr); 52 sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get())); 53 } 54 55 void ExpectException(jclass exception_class) { 56 EXPECT_TRUE(env_->ExceptionCheck()); 57 jthrowable exception = env_->ExceptionOccurred(); 58 EXPECT_NE(nullptr, exception); 59 env_->ExceptionClear(); 60 EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class)); 61 } 62 63 void ExpectClassFound(const char* name) { 64 EXPECT_NE(env_->FindClass(name), nullptr) << name; 65 EXPECT_FALSE(env_->ExceptionCheck()) << name; 66 } 67 68 void ExpectClassNotFound(const char* name) { 69 EXPECT_EQ(env_->FindClass(name), nullptr) << name; 70 EXPECT_TRUE(env_->ExceptionCheck()) << name; 71 env_->ExceptionClear(); 72 } 73 74 void CleanUpJniEnv() { 75 if (aioobe_ != nullptr) { 76 env_->DeleteGlobalRef(aioobe_); 77 aioobe_ = nullptr; 78 } 79 if (ase_ != nullptr) { 80 env_->DeleteGlobalRef(ase_); 81 ase_ = nullptr; 82 } 83 if (sioobe_ != nullptr) { 84 env_->DeleteGlobalRef(sioobe_); 85 sioobe_ = nullptr; 86 } 87 } 88 89 virtual void TearDown() OVERRIDE { 90 CleanUpJniEnv(); 91 CommonCompilerTest::TearDown(); 92 } 93 94 jclass GetPrimitiveClass(char descriptor) { 95 ScopedObjectAccess soa(env_); 96 mirror::Class* c = class_linker_->FindPrimitiveClass(descriptor); 97 CHECK(c != nullptr); 98 return soa.AddLocalReference<jclass>(c); 99 } 100 101 JavaVMExt* vm_; 102 JNIEnv* env_; 103 jclass aioobe_; 104 jclass ase_; 105 jclass sioobe_; 106 }; 107 108 TEST_F(JniInternalTest, AllocObject) { 109 jclass c = env_->FindClass("java/lang/String"); 110 ASSERT_NE(c, nullptr); 111 jobject o = env_->AllocObject(c); 112 ASSERT_NE(o, nullptr); 113 114 // We have an instance of the class we asked for... 115 ASSERT_TRUE(env_->IsInstanceOf(o, c)); 116 // ...whose fields haven't been initialized because 117 // we didn't call a constructor. 118 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I"))); 119 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I"))); 120 ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == nullptr); 121 } 122 123 TEST_F(JniInternalTest, GetVersion) { 124 ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion()); 125 } 126 127 TEST_F(JniInternalTest, FindClass) { 128 // Reference types... 129 ExpectClassFound("java/lang/String"); 130 // ...for arrays too, where you must include "L;". 131 ExpectClassFound("[Ljava/lang/String;"); 132 // Primitive arrays are okay too, if the primitive type is valid. 133 ExpectClassFound("[C"); 134 135 { 136 CheckJniAbortCatcher check_jni_abort_catcher; 137 env_->FindClass(nullptr); 138 check_jni_abort_catcher.Check("name == null"); 139 140 // We support . as well as / for compatibility, if -Xcheck:jni is off. 141 ExpectClassFound("java.lang.String"); 142 check_jni_abort_catcher.Check("illegal class name 'java.lang.String'"); 143 ExpectClassNotFound("Ljava.lang.String;"); 144 check_jni_abort_catcher.Check("illegal class name 'Ljava.lang.String;'"); 145 ExpectClassFound("[Ljava.lang.String;"); 146 check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'"); 147 ExpectClassNotFound("[java.lang.String"); 148 check_jni_abort_catcher.Check("illegal class name '[java.lang.String'"); 149 150 // You can't include the "L;" in a JNI class descriptor. 151 ExpectClassNotFound("Ljava/lang/String;"); 152 check_jni_abort_catcher.Check("illegal class name 'Ljava/lang/String;'"); 153 154 // But you must include it for an array of any reference type. 155 ExpectClassNotFound("[java/lang/String"); 156 check_jni_abort_catcher.Check("illegal class name '[java/lang/String'"); 157 158 ExpectClassNotFound("[K"); 159 check_jni_abort_catcher.Check("illegal class name '[K'"); 160 161 // Void arrays aren't allowed. 162 ExpectClassNotFound("[V"); 163 check_jni_abort_catcher.Check("illegal class name '[V'"); 164 } 165 166 // But primitive types aren't allowed... 167 ExpectClassNotFound("C"); 168 ExpectClassNotFound("V"); 169 ExpectClassNotFound("K"); 170 } 171 172 TEST_F(JniInternalTest, GetFieldID) { 173 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError"); 174 ASSERT_NE(jlnsfe, nullptr); 175 jclass c = env_->FindClass("java/lang/String"); 176 ASSERT_NE(c, nullptr); 177 178 // Wrong type. 179 jfieldID fid = env_->GetFieldID(c, "count", "J"); 180 EXPECT_EQ(nullptr, fid); 181 ExpectException(jlnsfe); 182 183 // Wrong type where type doesn't exist. 184 fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;"); 185 EXPECT_EQ(nullptr, fid); 186 ExpectException(jlnsfe); 187 188 // Wrong name. 189 fid = env_->GetFieldID(c, "Count", "I"); 190 EXPECT_EQ(nullptr, fid); 191 ExpectException(jlnsfe); 192 193 // Good declared field lookup. 194 fid = env_->GetFieldID(c, "count", "I"); 195 EXPECT_NE(nullptr, fid); 196 EXPECT_FALSE(env_->ExceptionCheck()); 197 198 // Good superclass field lookup. 199 c = env_->FindClass("java/lang/StringBuilder"); 200 fid = env_->GetFieldID(c, "count", "I"); 201 EXPECT_NE(nullptr, fid); 202 EXPECT_NE(fid, nullptr); 203 EXPECT_FALSE(env_->ExceptionCheck()); 204 205 // Not instance. 206 fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); 207 EXPECT_EQ(nullptr, fid); 208 ExpectException(jlnsfe); 209 210 // Bad arguments. 211 CheckJniAbortCatcher check_jni_abort_catcher; 212 fid = env_->GetFieldID(nullptr, "count", "I"); 213 EXPECT_EQ(nullptr, fid); 214 check_jni_abort_catcher.Check("java_class == null"); 215 fid = env_->GetFieldID(c, nullptr, "I"); 216 EXPECT_EQ(nullptr, fid); 217 check_jni_abort_catcher.Check("name == null"); 218 fid = env_->GetFieldID(c, "count", nullptr); 219 EXPECT_EQ(nullptr, fid); 220 check_jni_abort_catcher.Check("sig == null"); 221 } 222 223 TEST_F(JniInternalTest, GetStaticFieldID) { 224 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError"); 225 ASSERT_NE(jlnsfe, nullptr); 226 jclass c = env_->FindClass("java/lang/String"); 227 ASSERT_NE(c, nullptr); 228 229 // Wrong type. 230 jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J"); 231 EXPECT_EQ(nullptr, fid); 232 ExpectException(jlnsfe); 233 234 // Wrong type where type doesn't exist. 235 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;"); 236 EXPECT_EQ(nullptr, fid); 237 ExpectException(jlnsfe); 238 239 // Wrong name. 240 fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); 241 EXPECT_EQ(nullptr, fid); 242 ExpectException(jlnsfe); 243 244 // Good declared field lookup. 245 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); 246 EXPECT_NE(nullptr, fid); 247 EXPECT_NE(fid, nullptr); 248 EXPECT_FALSE(env_->ExceptionCheck()); 249 250 // Not static. 251 fid = env_->GetStaticFieldID(c, "count", "I"); 252 EXPECT_EQ(nullptr, fid); 253 ExpectException(jlnsfe); 254 255 // Bad arguments. 256 CheckJniAbortCatcher check_jni_abort_catcher; 257 fid = env_->GetStaticFieldID(nullptr, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); 258 EXPECT_EQ(nullptr, fid); 259 check_jni_abort_catcher.Check("java_class == null"); 260 fid = env_->GetStaticFieldID(c, nullptr, "Ljava/util/Comparator;"); 261 EXPECT_EQ(nullptr, fid); 262 check_jni_abort_catcher.Check("name == null"); 263 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", nullptr); 264 EXPECT_EQ(nullptr, fid); 265 check_jni_abort_catcher.Check("sig == null"); 266 } 267 268 TEST_F(JniInternalTest, GetMethodID) { 269 jclass jlobject = env_->FindClass("java/lang/Object"); 270 jclass jlstring = env_->FindClass("java/lang/String"); 271 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError"); 272 jclass jncrbc = env_->FindClass("java/nio/channels/ReadableByteChannel"); 273 274 // Sanity check that no exceptions are pending. 275 ASSERT_FALSE(env_->ExceptionCheck()); 276 277 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is 278 // a pending exception. 279 jmethodID method = env_->GetMethodID(jlobject, "foo", "()V"); 280 EXPECT_EQ(nullptr, method); 281 ExpectException(jlnsme); 282 283 // Check that java.lang.Object.equals() does exist. 284 method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z"); 285 EXPECT_NE(nullptr, method); 286 EXPECT_FALSE(env_->ExceptionCheck()); 287 288 // Check that GetMethodID for java.lang.String.valueOf(int) fails as the 289 // method is static. 290 method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;"); 291 EXPECT_EQ(nullptr, method); 292 ExpectException(jlnsme); 293 294 // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor. 295 method = env_->GetMethodID(jlnsme, "<init>", "(Ljava/lang/String;)V"); 296 EXPECT_NE(nullptr, method); 297 EXPECT_FALSE(env_->ExceptionCheck()); 298 299 // Check that GetMethodID can find a interface method inherited from another interface. 300 method = env_->GetMethodID(jncrbc, "close", "()V"); 301 EXPECT_NE(nullptr, method); 302 EXPECT_FALSE(env_->ExceptionCheck()); 303 304 // Bad arguments. 305 CheckJniAbortCatcher check_jni_abort_catcher; 306 method = env_->GetMethodID(nullptr, "<init>", "(Ljava/lang/String;)V"); 307 EXPECT_EQ(nullptr, method); 308 check_jni_abort_catcher.Check("java_class == null"); 309 method = env_->GetMethodID(jlnsme, nullptr, "(Ljava/lang/String;)V"); 310 EXPECT_EQ(nullptr, method); 311 check_jni_abort_catcher.Check("name == null"); 312 method = env_->GetMethodID(jlnsme, "<init>", nullptr); 313 EXPECT_EQ(nullptr, method); 314 check_jni_abort_catcher.Check("sig == null"); 315 } 316 317 TEST_F(JniInternalTest, CallVoidMethodNullReceiver) { 318 jclass jlobject = env_->FindClass("java/lang/Object"); 319 jmethodID method; 320 321 // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor. 322 method = env_->GetMethodID(jlobject, "<init>", "()V"); 323 EXPECT_NE(nullptr, method); 324 EXPECT_FALSE(env_->ExceptionCheck()); 325 326 // Null object to CallVoidMethod. 327 CheckJniAbortCatcher check_jni_abort_catcher; 328 method = env_->GetMethodID(nullptr, "<init>", "(Ljava/lang/String;)V"); 329 env_->CallVoidMethod(nullptr, method); 330 check_jni_abort_catcher.Check("null"); 331 } 332 333 TEST_F(JniInternalTest, GetStaticMethodID) { 334 jclass jlobject = env_->FindClass("java/lang/Object"); 335 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError"); 336 337 // Sanity check that no exceptions are pending 338 ASSERT_FALSE(env_->ExceptionCheck()); 339 340 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is 341 // a pending exception 342 jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V"); 343 EXPECT_EQ(nullptr, method); 344 ExpectException(jlnsme); 345 346 // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as 347 // the method is not static 348 method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z"); 349 EXPECT_EQ(nullptr, method); 350 ExpectException(jlnsme); 351 352 // Check that java.lang.String.valueOf(int) does exist 353 jclass jlstring = env_->FindClass("java/lang/String"); 354 method = env_->GetStaticMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;"); 355 EXPECT_NE(nullptr, method); 356 EXPECT_FALSE(env_->ExceptionCheck()); 357 358 // Bad arguments. 359 CheckJniAbortCatcher check_jni_abort_catcher; 360 method = env_->GetStaticMethodID(nullptr, "valueOf", "(I)Ljava/lang/String;"); 361 EXPECT_EQ(nullptr, method); 362 check_jni_abort_catcher.Check("java_class == null"); 363 method = env_->GetStaticMethodID(jlstring, nullptr, "(I)Ljava/lang/String;"); 364 EXPECT_EQ(nullptr, method); 365 check_jni_abort_catcher.Check("name == null"); 366 method = env_->GetStaticMethodID(jlstring, "valueOf", nullptr); 367 EXPECT_EQ(nullptr, method); 368 check_jni_abort_catcher.Check("sig == null"); 369 } 370 371 TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) { 372 jclass jlrField = env_->FindClass("java/lang/reflect/Field"); 373 jclass c = env_->FindClass("java/lang/String"); 374 ASSERT_NE(c, nullptr); 375 jfieldID fid = env_->GetFieldID(c, "count", "I"); 376 ASSERT_NE(fid, nullptr); 377 // Turn the fid into a java.lang.reflect.Field... 378 jobject field = env_->ToReflectedField(c, fid, JNI_FALSE); 379 ASSERT_NE(c, nullptr); 380 ASSERT_TRUE(env_->IsInstanceOf(field, jlrField)); 381 // ...and back again. 382 jfieldID fid2 = env_->FromReflectedField(field); 383 ASSERT_NE(fid2, nullptr); 384 // Make sure we can actually use it. 385 jstring s = env_->NewStringUTF("poop"); 386 ASSERT_EQ(4, env_->GetIntField(s, fid2)); 387 388 // Bad arguments. 389 CheckJniAbortCatcher check_jni_abort_catcher; 390 field = env_->ToReflectedField(c, nullptr, JNI_FALSE); 391 EXPECT_EQ(field, nullptr); 392 check_jni_abort_catcher.Check("fid == null"); 393 fid2 = env_->FromReflectedField(nullptr); 394 ASSERT_EQ(fid2, nullptr); 395 check_jni_abort_catcher.Check("jlr_field == null"); 396 } 397 398 TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) { 399 jclass jlrMethod = env_->FindClass("java/lang/reflect/Method"); 400 ASSERT_NE(jlrMethod, nullptr); 401 jclass jlrConstructor = env_->FindClass("java/lang/reflect/Constructor"); 402 ASSERT_NE(jlrConstructor, nullptr); 403 jclass c = env_->FindClass("java/lang/String"); 404 ASSERT_NE(c, nullptr); 405 406 jmethodID mid = env_->GetMethodID(c, "<init>", "()V"); 407 ASSERT_NE(mid, nullptr); 408 // Turn the mid into a java.lang.reflect.Constructor... 409 jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE); 410 ASSERT_NE(method, nullptr); 411 ASSERT_TRUE(env_->IsInstanceOf(method, jlrConstructor)); 412 // ...and back again. 413 jmethodID mid2 = env_->FromReflectedMethod(method); 414 ASSERT_NE(mid2, nullptr); 415 // Make sure we can actually use it. 416 jstring s = reinterpret_cast<jstring>(env_->AllocObject(c)); 417 ASSERT_NE(s, nullptr); 418 env_->CallVoidMethod(s, mid2); 419 ASSERT_EQ(JNI_FALSE, env_->ExceptionCheck()); 420 421 mid = env_->GetMethodID(c, "length", "()I"); 422 ASSERT_NE(mid, nullptr); 423 // Turn the mid into a java.lang.reflect.Method... 424 method = env_->ToReflectedMethod(c, mid, JNI_FALSE); 425 ASSERT_NE(method, nullptr); 426 ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod)); 427 // ...and back again. 428 mid2 = env_->FromReflectedMethod(method); 429 ASSERT_NE(mid2, nullptr); 430 // Make sure we can actually use it. 431 s = env_->NewStringUTF("poop"); 432 ASSERT_NE(s, nullptr); 433 ASSERT_EQ(4, env_->CallIntMethod(s, mid2)); 434 435 // Bad arguments. 436 CheckJniAbortCatcher check_jni_abort_catcher; 437 method = env_->ToReflectedMethod(c, nullptr, JNI_FALSE); 438 EXPECT_EQ(method, nullptr); 439 check_jni_abort_catcher.Check("mid == null"); 440 mid2 = env_->FromReflectedMethod(method); 441 ASSERT_EQ(mid2, nullptr); 442 check_jni_abort_catcher.Check("jlr_method == null"); 443 } 444 445 static void BogusMethod() { 446 // You can't pass nullptr function pointers to RegisterNatives. 447 } 448 449 TEST_F(JniInternalTest, RegisterAndUnregisterNatives) { 450 jclass jlobject = env_->FindClass("java/lang/Object"); 451 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError"); 452 void* native_function = reinterpret_cast<void*>(BogusMethod); 453 454 // Sanity check that no exceptions are pending. 455 ASSERT_FALSE(env_->ExceptionCheck()); 456 457 // Check that registering method without name causes a NoSuchMethodError. 458 { 459 JNINativeMethod methods[] = { { nullptr, "()V", native_function } }; 460 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); 461 } 462 ExpectException(jlnsme); 463 464 // Check that registering method without signature causes a NoSuchMethodError. 465 { 466 JNINativeMethod methods[] = { { "notify", nullptr, native_function } }; 467 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); 468 } 469 ExpectException(jlnsme); 470 471 // Check that registering method without function causes a NoSuchMethodError. 472 { 473 JNINativeMethod methods[] = { { "notify", "()V", nullptr } }; 474 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); 475 } 476 ExpectException(jlnsme); 477 478 // Check that registering to a non-existent java.lang.Object.foo() causes a NoSuchMethodError. 479 { 480 JNINativeMethod methods[] = { { "foo", "()V", native_function } }; 481 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); 482 } 483 ExpectException(jlnsme); 484 485 // Check that registering non-native methods causes a NoSuchMethodError. 486 { 487 JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", native_function } }; 488 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); 489 } 490 ExpectException(jlnsme); 491 492 // Check that registering native methods is successful. 493 { 494 JNINativeMethod methods[] = { { "notify", "()V", native_function } }; 495 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_OK); 496 } 497 EXPECT_FALSE(env_->ExceptionCheck()); 498 EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK); 499 500 // Check that registering no methods isn't a failure. 501 { 502 JNINativeMethod methods[] = { }; 503 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 0), JNI_OK); 504 } 505 EXPECT_FALSE(env_->ExceptionCheck()); 506 EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK); 507 508 // Check that registering a -ve number of methods is a failure. 509 CheckJniAbortCatcher check_jni_abort_catcher; 510 for (int i = -10; i < 0; ++i) { 511 JNINativeMethod methods[] = { }; 512 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, i), JNI_ERR); 513 check_jni_abort_catcher.Check("negative method count: "); 514 } 515 EXPECT_FALSE(env_->ExceptionCheck()); 516 517 // Passing a class of null is a failure. 518 { 519 JNINativeMethod methods[] = { }; 520 EXPECT_EQ(env_->RegisterNatives(nullptr, methods, 0), JNI_ERR); 521 check_jni_abort_catcher.Check("java_class == null"); 522 } 523 524 // Passing methods as null is a failure. 525 EXPECT_EQ(env_->RegisterNatives(jlobject, nullptr, 1), JNI_ERR); 526 check_jni_abort_catcher.Check("methods == null"); 527 528 // Unregisters null is a failure. 529 EXPECT_EQ(env_->UnregisterNatives(nullptr), JNI_ERR); 530 check_jni_abort_catcher.Check("java_class == null"); 531 532 // Unregistering a class with no natives is a warning. 533 EXPECT_EQ(env_->UnregisterNatives(jlnsme), JNI_OK); 534 } 535 536 #define EXPECT_PRIMITIVE_ARRAY(new_fn, \ 537 get_region_fn, \ 538 set_region_fn, \ 539 get_elements_fn, \ 540 release_elements_fn, \ 541 scalar_type, \ 542 expected_class_descriptor) \ 543 jsize size = 4; \ 544 \ 545 { \ 546 CheckJniAbortCatcher jni_abort_catcher; \ 547 /* Allocate an negative sized array and check it has the right failure type. */ \ 548 EXPECT_EQ(env_->new_fn(-1), nullptr); \ 549 jni_abort_catcher.Check("negative array length: -1"); \ 550 EXPECT_EQ(env_->new_fn(std::numeric_limits<jint>::min()), nullptr); \ 551 jni_abort_catcher.Check("negative array length: -2147483648"); \ 552 /* Pass the array as null. */ \ 553 EXPECT_EQ(0, env_->GetArrayLength(nullptr)); \ 554 jni_abort_catcher.Check("java_array == null"); \ 555 env_->get_region_fn(nullptr, 0, 0, nullptr); \ 556 jni_abort_catcher.Check("java_array == null"); \ 557 env_->set_region_fn(nullptr, 0, 0, nullptr); \ 558 jni_abort_catcher.Check("java_array == null"); \ 559 env_->get_elements_fn(nullptr, nullptr); \ 560 jni_abort_catcher.Check("java_array == null"); \ 561 env_->release_elements_fn(nullptr, nullptr, 0); \ 562 jni_abort_catcher.Check("java_array == null"); \ 563 /* Pass the elements for region as null. */ \ 564 scalar_type ## Array a = env_->new_fn(size); \ 565 env_->get_region_fn(a, 0, size, nullptr); \ 566 jni_abort_catcher.Check("buf == null"); \ 567 env_->set_region_fn(a, 0, size, nullptr); \ 568 jni_abort_catcher.Check("buf == null"); \ 569 } \ 570 /* Allocate an array and check it has the right type and length. */ \ 571 scalar_type ## Array a = env_->new_fn(size); \ 572 EXPECT_NE(a, nullptr); \ 573 EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \ 574 EXPECT_EQ(size, env_->GetArrayLength(a)); \ 575 \ 576 /* GetPrimitiveArrayRegion/SetPrimitiveArrayRegion */ \ 577 /* AIOOBE for negative start offset. */ \ 578 env_->get_region_fn(a, -1, 1, nullptr); \ 579 ExpectException(aioobe_); \ 580 env_->set_region_fn(a, -1, 1, nullptr); \ 581 ExpectException(aioobe_); \ 582 \ 583 /* AIOOBE for negative length. */ \ 584 env_->get_region_fn(a, 0, -1, nullptr); \ 585 ExpectException(aioobe_); \ 586 env_->set_region_fn(a, 0, -1, nullptr); \ 587 ExpectException(aioobe_); \ 588 \ 589 /* AIOOBE for buffer overrun. */ \ 590 env_->get_region_fn(a, size - 1, size, nullptr); \ 591 ExpectException(aioobe_); \ 592 env_->set_region_fn(a, size - 1, size, nullptr); \ 593 ExpectException(aioobe_); \ 594 \ 595 /* It's okay for the buffer to be nullptr as long as the length is 0. */ \ 596 env_->get_region_fn(a, 2, 0, nullptr); \ 597 /* Even if the offset is invalid... */ \ 598 env_->get_region_fn(a, 123, 0, nullptr); \ 599 ExpectException(aioobe_); \ 600 \ 601 /* It's okay for the buffer to be nullptr as long as the length is 0. */ \ 602 env_->set_region_fn(a, 2, 0, nullptr); \ 603 /* Even if the offset is invalid... */ \ 604 env_->set_region_fn(a, 123, 0, nullptr); \ 605 ExpectException(aioobe_); \ 606 \ 607 /* Prepare a couple of buffers. */ \ 608 std::unique_ptr<scalar_type[]> src_buf(new scalar_type[size]); \ 609 std::unique_ptr<scalar_type[]> dst_buf(new scalar_type[size]); \ 610 for (jsize i = 0; i < size; ++i) { src_buf[i] = scalar_type(i); } \ 611 for (jsize i = 0; i < size; ++i) { dst_buf[i] = scalar_type(-1); } \ 612 \ 613 /* Copy all of src_buf onto the heap. */ \ 614 env_->set_region_fn(a, 0, size, &src_buf[0]); \ 615 /* Copy back only part. */ \ 616 env_->get_region_fn(a, 1, size - 2, &dst_buf[1]); \ 617 EXPECT_NE(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \ 618 << "short copy equal"; \ 619 /* Copy the missing pieces. */ \ 620 env_->get_region_fn(a, 0, 1, &dst_buf[0]); \ 621 env_->get_region_fn(a, size - 1, 1, &dst_buf[size - 1]); \ 622 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \ 623 << "fixed copy not equal"; \ 624 /* Copy back the whole array. */ \ 625 env_->get_region_fn(a, 0, size, &dst_buf[0]); \ 626 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \ 627 << "full copy not equal"; \ 628 /* GetPrimitiveArrayCritical */ \ 629 void* v = env_->GetPrimitiveArrayCritical(a, nullptr); \ 630 EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) \ 631 << "GetPrimitiveArrayCritical not equal"; \ 632 env_->ReleasePrimitiveArrayCritical(a, v, 0); \ 633 /* GetXArrayElements */ \ 634 scalar_type* xs = env_->get_elements_fn(a, nullptr); \ 635 EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) \ 636 << # get_elements_fn " not equal"; \ 637 env_->release_elements_fn(a, xs, 0); \ 638 639 TEST_F(JniInternalTest, BooleanArrays) { 640 EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, GetBooleanArrayRegion, SetBooleanArrayRegion, 641 GetBooleanArrayElements, ReleaseBooleanArrayElements, jboolean, "[Z"); 642 } 643 TEST_F(JniInternalTest, ByteArrays) { 644 EXPECT_PRIMITIVE_ARRAY(NewByteArray, GetByteArrayRegion, SetByteArrayRegion, 645 GetByteArrayElements, ReleaseByteArrayElements, jbyte, "[B"); 646 } 647 TEST_F(JniInternalTest, CharArrays) { 648 EXPECT_PRIMITIVE_ARRAY(NewCharArray, GetCharArrayRegion, SetCharArrayRegion, 649 GetCharArrayElements, ReleaseCharArrayElements, jchar, "[C"); 650 } 651 TEST_F(JniInternalTest, DoubleArrays) { 652 EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, GetDoubleArrayRegion, SetDoubleArrayRegion, 653 GetDoubleArrayElements, ReleaseDoubleArrayElements, jdouble, "[D"); 654 } 655 TEST_F(JniInternalTest, FloatArrays) { 656 EXPECT_PRIMITIVE_ARRAY(NewFloatArray, GetFloatArrayRegion, SetFloatArrayRegion, 657 GetFloatArrayElements, ReleaseFloatArrayElements, jfloat, "[F"); 658 } 659 TEST_F(JniInternalTest, IntArrays) { 660 EXPECT_PRIMITIVE_ARRAY(NewIntArray, GetIntArrayRegion, SetIntArrayRegion, 661 GetIntArrayElements, ReleaseIntArrayElements, jint, "[I"); 662 } 663 TEST_F(JniInternalTest, LongArrays) { 664 EXPECT_PRIMITIVE_ARRAY(NewLongArray, GetLongArrayRegion, SetLongArrayRegion, 665 GetLongArrayElements, ReleaseLongArrayElements, jlong, "[J"); 666 } 667 TEST_F(JniInternalTest, ShortArrays) { 668 EXPECT_PRIMITIVE_ARRAY(NewShortArray, GetShortArrayRegion, SetShortArrayRegion, 669 GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S"); 670 } 671 672 TEST_F(JniInternalTest, GetPrimitiveArrayElementsOfWrongType) { 673 CheckJniAbortCatcher jni_abort_catcher; 674 jbooleanArray array = env_->NewBooleanArray(10); 675 jboolean is_copy; 676 EXPECT_EQ(env_->GetByteArrayElements(reinterpret_cast<jbyteArray>(array), &is_copy), nullptr); 677 jni_abort_catcher.Check( 678 "attempt to get byte primitive array elements with an object of type boolean[]"); 679 EXPECT_EQ(env_->GetShortArrayElements(reinterpret_cast<jshortArray>(array), &is_copy), nullptr); 680 jni_abort_catcher.Check( 681 "attempt to get short primitive array elements with an object of type boolean[]"); 682 EXPECT_EQ(env_->GetCharArrayElements(reinterpret_cast<jcharArray>(array), &is_copy), nullptr); 683 jni_abort_catcher.Check( 684 "attempt to get char primitive array elements with an object of type boolean[]"); 685 EXPECT_EQ(env_->GetIntArrayElements(reinterpret_cast<jintArray>(array), &is_copy), nullptr); 686 jni_abort_catcher.Check( 687 "attempt to get int primitive array elements with an object of type boolean[]"); 688 EXPECT_EQ(env_->GetLongArrayElements(reinterpret_cast<jlongArray>(array), &is_copy), nullptr); 689 jni_abort_catcher.Check( 690 "attempt to get long primitive array elements with an object of type boolean[]"); 691 EXPECT_EQ(env_->GetFloatArrayElements(reinterpret_cast<jfloatArray>(array), &is_copy), nullptr); 692 jni_abort_catcher.Check( 693 "attempt to get float primitive array elements with an object of type boolean[]"); 694 EXPECT_EQ(env_->GetDoubleArrayElements(reinterpret_cast<jdoubleArray>(array), &is_copy), nullptr); 695 jni_abort_catcher.Check( 696 "attempt to get double primitive array elements with an object of type boolean[]"); 697 jbyteArray array2 = env_->NewByteArray(10); 698 EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), &is_copy), 699 nullptr); 700 jni_abort_catcher.Check( 701 "attempt to get boolean primitive array elements with an object of type byte[]"); 702 jobject object = env_->NewStringUTF("Test String"); 703 EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), &is_copy), 704 nullptr); 705 jni_abort_catcher.Check( 706 "attempt to get boolean primitive array elements with an object of type java.lang.String"); 707 } 708 709 TEST_F(JniInternalTest, ReleasePrimitiveArrayElementsOfWrongType) { 710 CheckJniAbortCatcher jni_abort_catcher; 711 jbooleanArray array = env_->NewBooleanArray(10); 712 ASSERT_TRUE(array != nullptr); 713 jboolean is_copy; 714 jboolean* elements = env_->GetBooleanArrayElements(array, &is_copy); 715 ASSERT_TRUE(elements != nullptr); 716 env_->ReleaseByteArrayElements(reinterpret_cast<jbyteArray>(array), 717 reinterpret_cast<jbyte*>(elements), 0); 718 jni_abort_catcher.Check( 719 "attempt to release byte primitive array elements with an object of type boolean[]"); 720 env_->ReleaseShortArrayElements(reinterpret_cast<jshortArray>(array), 721 reinterpret_cast<jshort*>(elements), 0); 722 jni_abort_catcher.Check( 723 "attempt to release short primitive array elements with an object of type boolean[]"); 724 env_->ReleaseCharArrayElements(reinterpret_cast<jcharArray>(array), 725 reinterpret_cast<jchar*>(elements), 0); 726 jni_abort_catcher.Check( 727 "attempt to release char primitive array elements with an object of type boolean[]"); 728 env_->ReleaseIntArrayElements(reinterpret_cast<jintArray>(array), 729 reinterpret_cast<jint*>(elements), 0); 730 jni_abort_catcher.Check( 731 "attempt to release int primitive array elements with an object of type boolean[]"); 732 env_->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array), 733 reinterpret_cast<jlong*>(elements), 0); 734 jni_abort_catcher.Check( 735 "attempt to release long primitive array elements with an object of type boolean[]"); 736 env_->ReleaseFloatArrayElements(reinterpret_cast<jfloatArray>(array), 737 reinterpret_cast<jfloat*>(elements), 0); 738 jni_abort_catcher.Check( 739 "attempt to release float primitive array elements with an object of type boolean[]"); 740 env_->ReleaseDoubleArrayElements(reinterpret_cast<jdoubleArray>(array), 741 reinterpret_cast<jdouble*>(elements), 0); 742 jni_abort_catcher.Check( 743 "attempt to release double primitive array elements with an object of type boolean[]"); 744 jbyteArray array2 = env_->NewByteArray(10); 745 env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), elements, 0); 746 jni_abort_catcher.Check( 747 "attempt to release boolean primitive array elements with an object of type byte[]"); 748 jobject object = env_->NewStringUTF("Test String"); 749 env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), elements, 0); 750 jni_abort_catcher.Check( 751 "attempt to release boolean primitive array elements with an object of type " 752 "java.lang.String"); 753 } 754 TEST_F(JniInternalTest, GetReleasePrimitiveArrayCriticalOfWrongType) { 755 CheckJniAbortCatcher jni_abort_catcher; 756 jobject object = env_->NewStringUTF("Test String"); 757 jboolean is_copy; 758 void* elements = env_->GetPrimitiveArrayCritical(reinterpret_cast<jarray>(object), &is_copy); 759 jni_abort_catcher.Check("expected primitive array, given java.lang.String"); 760 env_->ReleasePrimitiveArrayCritical(reinterpret_cast<jarray>(object), elements, 0); 761 jni_abort_catcher.Check("expected primitive array, given java.lang.String"); 762 } 763 764 TEST_F(JniInternalTest, GetPrimitiveArrayRegionElementsOfWrongType) { 765 CheckJniAbortCatcher jni_abort_catcher; 766 constexpr size_t kLength = 10; 767 jbooleanArray array = env_->NewBooleanArray(kLength); 768 ASSERT_TRUE(array != nullptr); 769 jboolean elements[kLength]; 770 env_->GetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength, 771 reinterpret_cast<jbyte*>(elements)); 772 jni_abort_catcher.Check( 773 "attempt to get region of byte primitive array elements with an object of type boolean[]"); 774 env_->GetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength, 775 reinterpret_cast<jshort*>(elements)); 776 jni_abort_catcher.Check( 777 "attempt to get region of short primitive array elements with an object of type boolean[]"); 778 env_->GetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength, 779 reinterpret_cast<jchar*>(elements)); 780 jni_abort_catcher.Check( 781 "attempt to get region of char primitive array elements with an object of type boolean[]"); 782 env_->GetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength, 783 reinterpret_cast<jint*>(elements)); 784 jni_abort_catcher.Check( 785 "attempt to get region of int primitive array elements with an object of type boolean[]"); 786 env_->GetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength, 787 reinterpret_cast<jlong*>(elements)); 788 jni_abort_catcher.Check( 789 "attempt to get region of long primitive array elements with an object of type boolean[]"); 790 env_->GetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength, 791 reinterpret_cast<jfloat*>(elements)); 792 jni_abort_catcher.Check( 793 "attempt to get region of float primitive array elements with an object of type boolean[]"); 794 env_->GetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength, 795 reinterpret_cast<jdouble*>(elements)); 796 jni_abort_catcher.Check( 797 "attempt to get region of double primitive array elements with an object of type boolean[]"); 798 jbyteArray array2 = env_->NewByteArray(10); 799 env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength, 800 reinterpret_cast<jboolean*>(elements)); 801 jni_abort_catcher.Check( 802 "attempt to get region of boolean primitive array elements with an object of type byte[]"); 803 jobject object = env_->NewStringUTF("Test String"); 804 env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength, 805 reinterpret_cast<jboolean*>(elements)); 806 jni_abort_catcher.Check( 807 "attempt to get region of boolean primitive array elements with an object of type " 808 "java.lang.String"); 809 } 810 811 TEST_F(JniInternalTest, SetPrimitiveArrayRegionElementsOfWrongType) { 812 CheckJniAbortCatcher jni_abort_catcher; 813 constexpr size_t kLength = 10; 814 jbooleanArray array = env_->NewBooleanArray(kLength); 815 ASSERT_TRUE(array != nullptr); 816 jboolean elements[kLength]; 817 env_->SetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength, 818 reinterpret_cast<jbyte*>(elements)); 819 jni_abort_catcher.Check( 820 "attempt to set region of byte primitive array elements with an object of type boolean[]"); 821 env_->SetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength, 822 reinterpret_cast<jshort*>(elements)); 823 jni_abort_catcher.Check( 824 "attempt to set region of short primitive array elements with an object of type boolean[]"); 825 env_->SetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength, 826 reinterpret_cast<jchar*>(elements)); 827 jni_abort_catcher.Check( 828 "attempt to set region of char primitive array elements with an object of type boolean[]"); 829 env_->SetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength, 830 reinterpret_cast<jint*>(elements)); 831 jni_abort_catcher.Check( 832 "attempt to set region of int primitive array elements with an object of type boolean[]"); 833 env_->SetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength, 834 reinterpret_cast<jlong*>(elements)); 835 jni_abort_catcher.Check( 836 "attempt to set region of long primitive array elements with an object of type boolean[]"); 837 env_->SetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength, 838 reinterpret_cast<jfloat*>(elements)); 839 jni_abort_catcher.Check( 840 "attempt to set region of float primitive array elements with an object of type boolean[]"); 841 env_->SetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength, 842 reinterpret_cast<jdouble*>(elements)); 843 jni_abort_catcher.Check( 844 "attempt to set region of double primitive array elements with an object of type boolean[]"); 845 jbyteArray array2 = env_->NewByteArray(10); 846 env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength, 847 reinterpret_cast<jboolean*>(elements)); 848 jni_abort_catcher.Check( 849 "attempt to set region of boolean primitive array elements with an object of type byte[]"); 850 jobject object = env_->NewStringUTF("Test String"); 851 env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength, 852 reinterpret_cast<jboolean*>(elements)); 853 jni_abort_catcher.Check( 854 "attempt to set region of boolean primitive array elements with an object of type " 855 "java.lang.String"); 856 } 857 858 TEST_F(JniInternalTest, NewObjectArray) { 859 jclass element_class = env_->FindClass("java/lang/String"); 860 ASSERT_NE(element_class, nullptr); 861 jclass array_class = env_->FindClass("[Ljava/lang/String;"); 862 ASSERT_NE(array_class, nullptr); 863 864 jobjectArray a = env_->NewObjectArray(0, element_class, nullptr); 865 EXPECT_NE(a, nullptr); 866 EXPECT_TRUE(env_->IsInstanceOf(a, array_class)); 867 EXPECT_EQ(0, env_->GetArrayLength(a)); 868 869 a = env_->NewObjectArray(1, element_class, nullptr); 870 EXPECT_NE(a, nullptr); 871 EXPECT_TRUE(env_->IsInstanceOf(a, array_class)); 872 EXPECT_EQ(1, env_->GetArrayLength(a)); 873 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), nullptr)); 874 875 // Negative array length checks. 876 CheckJniAbortCatcher jni_abort_catcher; 877 env_->NewObjectArray(-1, element_class, nullptr); 878 jni_abort_catcher.Check("negative array length: -1"); 879 880 env_->NewObjectArray(std::numeric_limits<jint>::min(), element_class, nullptr); 881 jni_abort_catcher.Check("negative array length: -2147483648"); 882 } 883 884 TEST_F(JniInternalTest, NewObjectArrayWithPrimitiveClasses) { 885 const char* primitive_descriptors = "VZBSCIJFD"; 886 const char* primitive_names[] = { 887 "void", "boolean", "byte", "short", "char", "int", "long", "float", "double" 888 }; 889 ASSERT_EQ(strlen(primitive_descriptors), arraysize(primitive_names)); 890 891 CheckJniAbortCatcher jni_abort_catcher; 892 for (size_t i = 0; i < strlen(primitive_descriptors); ++i) { 893 env_->NewObjectArray(0, nullptr, nullptr); 894 jni_abort_catcher.Check("element_jclass == null"); 895 jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]); 896 env_->NewObjectArray(1, primitive_class, nullptr); 897 std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i])); 898 jni_abort_catcher.Check(error_msg.c_str()); 899 } 900 } 901 902 TEST_F(JniInternalTest, NewObjectArrayWithInitialValue) { 903 jclass element_class = env_->FindClass("java/lang/String"); 904 ASSERT_NE(element_class, nullptr); 905 jclass array_class = env_->FindClass("[Ljava/lang/String;"); 906 ASSERT_NE(array_class, nullptr); 907 908 jstring s = env_->NewStringUTF("poop"); 909 jobjectArray a = env_->NewObjectArray(2, element_class, s); 910 EXPECT_NE(a, nullptr); 911 EXPECT_TRUE(env_->IsInstanceOf(a, array_class)); 912 EXPECT_EQ(2, env_->GetArrayLength(a)); 913 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s)); 914 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 1), s)); 915 916 // Attempt to incorrect create an array of strings with initial value of string arrays. 917 CheckJniAbortCatcher jni_abort_catcher; 918 env_->NewObjectArray(2, element_class, a); 919 jni_abort_catcher.Check("cannot assign object of type 'java.lang.String[]' to array with element " 920 "type of 'java.lang.String'"); 921 } 922 923 TEST_F(JniInternalTest, GetArrayLength) { 924 // Already tested in NewObjectArray/NewPrimitiveArray. 925 } 926 927 TEST_F(JniInternalTest, GetObjectClass) { 928 jclass string_class = env_->FindClass("java/lang/String"); 929 ASSERT_NE(string_class, nullptr); 930 jclass class_class = env_->FindClass("java/lang/Class"); 931 ASSERT_NE(class_class, nullptr); 932 933 jstring s = env_->NewStringUTF("poop"); 934 jclass c = env_->GetObjectClass(s); 935 ASSERT_TRUE(env_->IsSameObject(string_class, c)); 936 937 jclass c2 = env_->GetObjectClass(c); 938 ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2))); 939 940 // Null as object should fail. 941 CheckJniAbortCatcher jni_abort_catcher; 942 EXPECT_EQ(env_->GetObjectClass(nullptr), nullptr); 943 jni_abort_catcher.Check("java_object == null"); 944 } 945 946 TEST_F(JniInternalTest, GetSuperclass) { 947 jclass object_class = env_->FindClass("java/lang/Object"); 948 ASSERT_NE(object_class, nullptr); 949 jclass string_class = env_->FindClass("java/lang/String"); 950 ASSERT_NE(string_class, nullptr); 951 jclass runnable_interface = env_->FindClass("java/lang/Runnable"); 952 ASSERT_NE(runnable_interface, nullptr); 953 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class))); 954 ASSERT_EQ(env_->GetSuperclass(object_class), nullptr); 955 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface))); 956 957 // Null as class should fail. 958 CheckJniAbortCatcher jni_abort_catcher; 959 EXPECT_EQ(env_->GetSuperclass(nullptr), nullptr); 960 jni_abort_catcher.Check("java_class == null"); 961 } 962 963 TEST_F(JniInternalTest, IsAssignableFrom) { 964 jclass object_class = env_->FindClass("java/lang/Object"); 965 ASSERT_NE(object_class, nullptr); 966 jclass string_class = env_->FindClass("java/lang/String"); 967 ASSERT_NE(string_class, nullptr); 968 969 // A superclass is assignable from an instance of its 970 // subclass but not vice versa. 971 ASSERT_TRUE(env_->IsAssignableFrom(string_class, object_class)); 972 ASSERT_FALSE(env_->IsAssignableFrom(object_class, string_class)); 973 974 jclass charsequence_interface = env_->FindClass("java/lang/CharSequence"); 975 ASSERT_NE(charsequence_interface, nullptr); 976 977 // An interface is assignable from an instance of an implementing 978 // class but not vice versa. 979 ASSERT_TRUE(env_->IsAssignableFrom(string_class, charsequence_interface)); 980 ASSERT_FALSE(env_->IsAssignableFrom(charsequence_interface, string_class)); 981 982 // Check that arrays are covariant. 983 jclass string_array_class = env_->FindClass("[Ljava/lang/String;"); 984 ASSERT_NE(string_array_class, nullptr); 985 jclass object_array_class = env_->FindClass("[Ljava/lang/Object;"); 986 ASSERT_NE(object_array_class, nullptr); 987 ASSERT_TRUE(env_->IsAssignableFrom(string_array_class, object_array_class)); 988 ASSERT_FALSE(env_->IsAssignableFrom(object_array_class, string_array_class)); 989 990 // Primitive types are tested in 004-JniTest. 991 992 // Null as either class should fail. 993 CheckJniAbortCatcher jni_abort_catcher; 994 EXPECT_EQ(env_->IsAssignableFrom(nullptr, string_class), JNI_FALSE); 995 jni_abort_catcher.Check("java_class1 == null"); 996 EXPECT_EQ(env_->IsAssignableFrom(object_class, nullptr), JNI_FALSE); 997 jni_abort_catcher.Check("java_class2 == null"); 998 } 999 1000 TEST_F(JniInternalTest, GetObjectRefType) { 1001 jclass local = env_->FindClass("java/lang/Object"); 1002 ASSERT_TRUE(local != nullptr); 1003 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local)); 1004 1005 jobject global = env_->NewGlobalRef(local); 1006 EXPECT_EQ(JNIGlobalRefType, env_->GetObjectRefType(global)); 1007 1008 jweak weak_global = env_->NewWeakGlobalRef(local); 1009 EXPECT_EQ(JNIWeakGlobalRefType, env_->GetObjectRefType(weak_global)); 1010 1011 jobject invalid = reinterpret_cast<jobject>(this); 1012 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid)); 1013 1014 // TODO: invoke a native method and test that its arguments are considered local references. 1015 1016 // Null as object should fail. 1017 CheckJniAbortCatcher jni_abort_catcher; 1018 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(nullptr)); 1019 jni_abort_catcher.Check("java_object == null"); 1020 } 1021 1022 TEST_F(JniInternalTest, StaleWeakGlobal) { 1023 jclass java_lang_Class = env_->FindClass("java/lang/Class"); 1024 ASSERT_NE(java_lang_Class, nullptr); 1025 jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, nullptr); 1026 ASSERT_NE(local_ref, nullptr); 1027 jweak weak_global = env_->NewWeakGlobalRef(local_ref); 1028 ASSERT_NE(weak_global, nullptr); 1029 env_->DeleteLocalRef(local_ref); 1030 Runtime::Current()->GetHeap()->CollectGarbage(false); // GC should clear the weak global. 1031 jobject new_global_ref = env_->NewGlobalRef(weak_global); 1032 EXPECT_EQ(new_global_ref, nullptr); 1033 jobject new_local_ref = env_->NewLocalRef(weak_global); 1034 EXPECT_EQ(new_local_ref, nullptr); 1035 } 1036 1037 TEST_F(JniInternalTest, NewStringUTF) { 1038 EXPECT_EQ(env_->NewStringUTF(nullptr), nullptr); 1039 jstring s; 1040 1041 s = env_->NewStringUTF(""); 1042 EXPECT_NE(s, nullptr); 1043 EXPECT_EQ(0, env_->GetStringLength(s)); 1044 EXPECT_EQ(0, env_->GetStringUTFLength(s)); 1045 s = env_->NewStringUTF("hello"); 1046 EXPECT_NE(s, nullptr); 1047 EXPECT_EQ(5, env_->GetStringLength(s)); 1048 EXPECT_EQ(5, env_->GetStringUTFLength(s)); 1049 1050 // TODO: check some non-ASCII strings. 1051 } 1052 1053 TEST_F(JniInternalTest, NewString) { 1054 jchar chars[] = { 'h', 'i' }; 1055 jstring s; 1056 s = env_->NewString(chars, 0); 1057 EXPECT_NE(s, nullptr); 1058 EXPECT_EQ(0, env_->GetStringLength(s)); 1059 EXPECT_EQ(0, env_->GetStringUTFLength(s)); 1060 s = env_->NewString(chars, 2); 1061 EXPECT_NE(s, nullptr); 1062 EXPECT_EQ(2, env_->GetStringLength(s)); 1063 EXPECT_EQ(2, env_->GetStringUTFLength(s)); 1064 1065 // TODO: check some non-ASCII strings. 1066 } 1067 1068 TEST_F(JniInternalTest, NewStringNullCharsZeroLength) { 1069 jstring s = env_->NewString(nullptr, 0); 1070 EXPECT_NE(s, nullptr); 1071 EXPECT_EQ(0, env_->GetStringLength(s)); 1072 } 1073 1074 TEST_F(JniInternalTest, NewStringNullCharsNonzeroLength) { 1075 CheckJniAbortCatcher jni_abort_catcher; 1076 env_->NewString(nullptr, 1); 1077 jni_abort_catcher.Check("chars == null && char_count > 0"); 1078 } 1079 1080 TEST_F(JniInternalTest, NewStringNegativeLength) { 1081 CheckJniAbortCatcher jni_abort_catcher; 1082 env_->NewString(nullptr, -1); 1083 jni_abort_catcher.Check("char_count < 0: -1"); 1084 env_->NewString(nullptr, std::numeric_limits<jint>::min()); 1085 jni_abort_catcher.Check("char_count < 0: -2147483648"); 1086 } 1087 1088 TEST_F(JniInternalTest, GetStringLength_GetStringUTFLength) { 1089 // Already tested in the NewString/NewStringUTF tests. 1090 } 1091 1092 TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) { 1093 jstring s = env_->NewStringUTF("hello"); 1094 ASSERT_TRUE(s != nullptr); 1095 1096 env_->GetStringRegion(s, -1, 0, nullptr); 1097 ExpectException(sioobe_); 1098 env_->GetStringRegion(s, 0, -1, nullptr); 1099 ExpectException(sioobe_); 1100 env_->GetStringRegion(s, 0, 10, nullptr); 1101 ExpectException(sioobe_); 1102 env_->GetStringRegion(s, 10, 1, nullptr); 1103 ExpectException(sioobe_); 1104 1105 jchar chars[4] = { 'x', 'x', 'x', 'x' }; 1106 env_->GetStringRegion(s, 1, 2, &chars[1]); 1107 EXPECT_EQ('x', chars[0]); 1108 EXPECT_EQ('e', chars[1]); 1109 EXPECT_EQ('l', chars[2]); 1110 EXPECT_EQ('x', chars[3]); 1111 1112 // It's okay for the buffer to be nullptr as long as the length is 0. 1113 env_->GetStringRegion(s, 2, 0, nullptr); 1114 // Even if the offset is invalid... 1115 env_->GetStringRegion(s, 123, 0, nullptr); 1116 ExpectException(sioobe_); 1117 1118 env_->GetStringUTFRegion(s, -1, 0, nullptr); 1119 ExpectException(sioobe_); 1120 env_->GetStringUTFRegion(s, 0, -1, nullptr); 1121 ExpectException(sioobe_); 1122 env_->GetStringUTFRegion(s, 0, 10, nullptr); 1123 ExpectException(sioobe_); 1124 env_->GetStringUTFRegion(s, 10, 1, nullptr); 1125 ExpectException(sioobe_); 1126 1127 char bytes[4] = { 'x', 'x', 'x', 'x' }; 1128 env_->GetStringUTFRegion(s, 1, 2, &bytes[1]); 1129 EXPECT_EQ('x', bytes[0]); 1130 EXPECT_EQ('e', bytes[1]); 1131 EXPECT_EQ('l', bytes[2]); 1132 EXPECT_EQ('x', bytes[3]); 1133 1134 // It's okay for the buffer to be nullptr as long as the length is 0. 1135 env_->GetStringUTFRegion(s, 2, 0, nullptr); 1136 // Even if the offset is invalid... 1137 env_->GetStringUTFRegion(s, 123, 0, nullptr); 1138 ExpectException(sioobe_); 1139 } 1140 1141 TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) { 1142 // Passing in a nullptr jstring is ignored normally, but caught by -Xcheck:jni. 1143 { 1144 CheckJniAbortCatcher check_jni_abort_catcher; 1145 EXPECT_EQ(env_->GetStringUTFChars(nullptr, nullptr), nullptr); 1146 check_jni_abort_catcher.Check("GetStringUTFChars received null jstring"); 1147 } 1148 1149 jstring s = env_->NewStringUTF("hello"); 1150 ASSERT_TRUE(s != nullptr); 1151 1152 const char* utf = env_->GetStringUTFChars(s, nullptr); 1153 EXPECT_STREQ("hello", utf); 1154 env_->ReleaseStringUTFChars(s, utf); 1155 1156 jboolean is_copy = JNI_FALSE; 1157 utf = env_->GetStringUTFChars(s, &is_copy); 1158 EXPECT_EQ(JNI_TRUE, is_copy); 1159 EXPECT_STREQ("hello", utf); 1160 env_->ReleaseStringUTFChars(s, utf); 1161 } 1162 1163 TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) { 1164 jstring s = env_->NewStringUTF("hello"); 1165 ScopedObjectAccess soa(env_); 1166 mirror::String* s_m = soa.Decode<mirror::String*>(s); 1167 ASSERT_TRUE(s != nullptr); 1168 1169 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' }; 1170 const jchar* chars = env_->GetStringChars(s, nullptr); 1171 EXPECT_EQ(expected[0], chars[0]); 1172 EXPECT_EQ(expected[1], chars[1]); 1173 EXPECT_EQ(expected[2], chars[2]); 1174 EXPECT_EQ(expected[3], chars[3]); 1175 EXPECT_EQ(expected[4], chars[4]); 1176 env_->ReleaseStringChars(s, chars); 1177 1178 jboolean is_copy = JNI_FALSE; 1179 chars = env_->GetStringChars(s, &is_copy); 1180 if (Runtime::Current()->GetHeap()->IsMovableObject(s_m->GetCharArray())) { 1181 EXPECT_EQ(JNI_TRUE, is_copy); 1182 } else { 1183 EXPECT_EQ(JNI_FALSE, is_copy); 1184 } 1185 EXPECT_EQ(expected[0], chars[0]); 1186 EXPECT_EQ(expected[1], chars[1]); 1187 EXPECT_EQ(expected[2], chars[2]); 1188 EXPECT_EQ(expected[3], chars[3]); 1189 EXPECT_EQ(expected[4], chars[4]); 1190 env_->ReleaseStringChars(s, chars); 1191 } 1192 1193 TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) { 1194 jstring s = env_->NewStringUTF("hello"); 1195 ASSERT_TRUE(s != nullptr); 1196 1197 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' }; 1198 const jchar* chars = env_->GetStringCritical(s, nullptr); 1199 EXPECT_EQ(expected[0], chars[0]); 1200 EXPECT_EQ(expected[1], chars[1]); 1201 EXPECT_EQ(expected[2], chars[2]); 1202 EXPECT_EQ(expected[3], chars[3]); 1203 EXPECT_EQ(expected[4], chars[4]); 1204 env_->ReleaseStringCritical(s, chars); 1205 1206 jboolean is_copy = JNI_TRUE; 1207 chars = env_->GetStringCritical(s, &is_copy); 1208 EXPECT_EQ(JNI_FALSE, is_copy); 1209 EXPECT_EQ(expected[0], chars[0]); 1210 EXPECT_EQ(expected[1], chars[1]); 1211 EXPECT_EQ(expected[2], chars[2]); 1212 EXPECT_EQ(expected[3], chars[3]); 1213 EXPECT_EQ(expected[4], chars[4]); 1214 env_->ReleaseStringCritical(s, chars); 1215 } 1216 1217 TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) { 1218 jclass java_lang_Class = env_->FindClass("java/lang/Class"); 1219 ASSERT_TRUE(java_lang_Class != nullptr); 1220 1221 jobjectArray array = env_->NewObjectArray(1, java_lang_Class, nullptr); 1222 EXPECT_NE(array, nullptr); 1223 EXPECT_EQ(env_->GetObjectArrayElement(array, 0), nullptr); 1224 env_->SetObjectArrayElement(array, 0, java_lang_Class); 1225 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class)); 1226 1227 // ArrayIndexOutOfBounds for negative index. 1228 env_->SetObjectArrayElement(array, -1, java_lang_Class); 1229 ExpectException(aioobe_); 1230 1231 // ArrayIndexOutOfBounds for too-large index. 1232 env_->SetObjectArrayElement(array, 1, java_lang_Class); 1233 ExpectException(aioobe_); 1234 1235 // ArrayStoreException thrown for bad types. 1236 env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!")); 1237 ExpectException(ase_); 1238 1239 // Null as array should fail. 1240 CheckJniAbortCatcher jni_abort_catcher; 1241 EXPECT_EQ(nullptr, env_->GetObjectArrayElement(nullptr, 0)); 1242 jni_abort_catcher.Check("java_array == null"); 1243 env_->SetObjectArrayElement(nullptr, 0, nullptr); 1244 jni_abort_catcher.Check("java_array == null"); 1245 } 1246 1247 #define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \ 1248 do { \ 1249 jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \ 1250 EXPECT_NE(fid, nullptr); \ 1251 env_->SetStatic ## type ## Field(c, fid, value1); \ 1252 EXPECT_EQ(value1, env_->GetStatic ## type ## Field(c, fid)); \ 1253 env_->SetStatic ## type ## Field(c, fid, value2); \ 1254 EXPECT_EQ(value2, env_->GetStatic ## type ## Field(c, fid)); \ 1255 \ 1256 CheckJniAbortCatcher jni_abort_catcher; \ 1257 env_->GetStatic ## type ## Field(nullptr, fid); \ 1258 jni_abort_catcher.Check("received null jclass"); \ 1259 env_->SetStatic ## type ## Field(nullptr, fid, value1); \ 1260 jni_abort_catcher.Check("received null jclass"); \ 1261 env_->GetStatic ## type ## Field(c, nullptr); \ 1262 jni_abort_catcher.Check("fid == null"); \ 1263 env_->SetStatic ## type ## Field(c, nullptr, value1); \ 1264 jni_abort_catcher.Check("fid == null"); \ 1265 } while (false) 1266 1267 #define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \ 1268 do { \ 1269 jfieldID fid = env_->GetFieldID(c, field_name, sig); \ 1270 EXPECT_NE(fid, nullptr); \ 1271 env_->Set ## type ## Field(instance, fid, value1); \ 1272 EXPECT_EQ(value1, env_->Get ## type ## Field(instance, fid)); \ 1273 env_->Set ## type ## Field(instance, fid, value2); \ 1274 EXPECT_EQ(value2, env_->Get ## type ## Field(instance, fid)); \ 1275 \ 1276 CheckJniAbortCatcher jni_abort_catcher; \ 1277 env_->Get ## type ## Field(nullptr, fid); \ 1278 jni_abort_catcher.Check("obj == null"); \ 1279 env_->Set ## type ## Field(nullptr, fid, value1); \ 1280 jni_abort_catcher.Check("obj == null"); \ 1281 env_->Get ## type ## Field(instance, nullptr); \ 1282 jni_abort_catcher.Check("fid == null"); \ 1283 env_->Set ## type ## Field(instance, nullptr, value1); \ 1284 jni_abort_catcher.Check("fid == null"); \ 1285 } while (false) 1286 1287 1288 TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) { 1289 TEST_DISABLED_FOR_PORTABLE(); 1290 Thread::Current()->TransitionFromSuspendedToRunnable(); 1291 LoadDex("AllFields"); 1292 bool started = runtime_->Start(); 1293 ASSERT_TRUE(started); 1294 1295 jclass c = env_->FindClass("AllFields"); 1296 ASSERT_NE(c, nullptr); 1297 jobject o = env_->AllocObject(c); 1298 ASSERT_NE(o, nullptr); 1299 1300 EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", JNI_TRUE, JNI_FALSE); 1301 EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2); 1302 EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b'); 1303 EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0); 1304 EXPECT_STATIC_PRIMITIVE_FIELD(Float, "sF", "F", 1.0, 2.0); 1305 EXPECT_STATIC_PRIMITIVE_FIELD(Int, "sI", "I", 1, 2); 1306 EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2); 1307 EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2); 1308 1309 EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", JNI_TRUE, JNI_FALSE); 1310 EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2); 1311 EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b'); 1312 EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0); 1313 EXPECT_PRIMITIVE_FIELD(o, Float, "iF", "F", 1.0, 2.0); 1314 EXPECT_PRIMITIVE_FIELD(o, Int, "iI", "I", 1, 2); 1315 EXPECT_PRIMITIVE_FIELD(o, Long, "iJ", "J", 1, 2); 1316 EXPECT_PRIMITIVE_FIELD(o, Short, "iS", "S", 1, 2); 1317 } 1318 1319 TEST_F(JniInternalTest, GetObjectField_SetObjectField) { 1320 TEST_DISABLED_FOR_PORTABLE(); 1321 Thread::Current()->TransitionFromSuspendedToRunnable(); 1322 LoadDex("AllFields"); 1323 runtime_->Start(); 1324 1325 jclass c = env_->FindClass("AllFields"); 1326 ASSERT_NE(c, nullptr); 1327 jobject o = env_->AllocObject(c); 1328 ASSERT_NE(o, nullptr); 1329 1330 jstring s1 = env_->NewStringUTF("hello"); 1331 ASSERT_NE(s1, nullptr); 1332 jstring s2 = env_->NewStringUTF("world"); 1333 ASSERT_NE(s2, nullptr); 1334 1335 jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;"); 1336 ASSERT_NE(s_fid, nullptr); 1337 jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;"); 1338 ASSERT_NE(i_fid, nullptr); 1339 1340 env_->SetStaticObjectField(c, s_fid, s1); 1341 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid))); 1342 env_->SetStaticObjectField(c, s_fid, s2); 1343 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetStaticObjectField(c, s_fid))); 1344 1345 env_->SetObjectField(o, i_fid, s1); 1346 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetObjectField(o, i_fid))); 1347 env_->SetObjectField(o, i_fid, s2); 1348 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid))); 1349 } 1350 1351 TEST_F(JniInternalTest, NewLocalRef_nullptr) { 1352 EXPECT_EQ(env_->NewLocalRef(nullptr), nullptr); 1353 } 1354 1355 TEST_F(JniInternalTest, NewLocalRef) { 1356 jstring s = env_->NewStringUTF(""); 1357 ASSERT_NE(s, nullptr); 1358 jobject o = env_->NewLocalRef(s); 1359 EXPECT_NE(o, nullptr); 1360 EXPECT_NE(o, s); 1361 1362 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o)); 1363 } 1364 1365 TEST_F(JniInternalTest, DeleteLocalRef_nullptr) { 1366 env_->DeleteLocalRef(nullptr); 1367 } 1368 1369 TEST_F(JniInternalTest, DeleteLocalRef) { 1370 jstring s = env_->NewStringUTF(""); 1371 ASSERT_NE(s, nullptr); 1372 env_->DeleteLocalRef(s); 1373 1374 // Currently, deleting an already-deleted reference is just a CheckJNI warning. 1375 { 1376 CheckJniAbortCatcher check_jni_abort_catcher; 1377 env_->DeleteLocalRef(s); 1378 1379 std::string expected(StringPrintf("native code passing in reference to " 1380 "invalid local reference: %p", s)); 1381 check_jni_abort_catcher.Check(expected.c_str()); 1382 } 1383 1384 s = env_->NewStringUTF(""); 1385 ASSERT_NE(s, nullptr); 1386 jobject o = env_->NewLocalRef(s); 1387 ASSERT_NE(o, nullptr); 1388 1389 env_->DeleteLocalRef(s); 1390 env_->DeleteLocalRef(o); 1391 } 1392 1393 TEST_F(JniInternalTest, PushLocalFrame_10395422) { 1394 // The JNI specification is ambiguous about whether the given capacity is to be interpreted as a 1395 // maximum or as a minimum, but it seems like it's supposed to be a minimum, and that's how 1396 // Android historically treated it, and it's how the RI treats it. It's also the more useful 1397 // interpretation! 1398 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(0)); 1399 env_->PopLocalFrame(nullptr); 1400 1401 // Negative capacities are not allowed. 1402 ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1)); 1403 1404 // And it's okay to have an upper limit. Ours is currently 512. 1405 ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(8192)); 1406 } 1407 1408 TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) { 1409 jobject original = env_->NewStringUTF(""); 1410 ASSERT_NE(original, nullptr); 1411 1412 jobject outer; 1413 jobject inner1, inner2; 1414 ScopedObjectAccess soa(env_); 1415 mirror::Object* inner2_direct_pointer; 1416 { 1417 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4)); 1418 outer = env_->NewLocalRef(original); 1419 1420 { 1421 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4)); 1422 inner1 = env_->NewLocalRef(outer); 1423 inner2 = env_->NewStringUTF("survivor"); 1424 inner2_direct_pointer = soa.Decode<mirror::Object*>(inner2); 1425 env_->PopLocalFrame(inner2); 1426 } 1427 1428 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original)); 1429 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(outer)); 1430 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1)); 1431 1432 // Our local reference for the survivor is invalid because the survivor 1433 // gets a new local reference... 1434 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2)); 1435 1436 env_->PopLocalFrame(nullptr); 1437 } 1438 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original)); 1439 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer)); 1440 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1)); 1441 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2)); 1442 } 1443 1444 TEST_F(JniInternalTest, NewGlobalRef_nullptr) { 1445 EXPECT_EQ(env_->NewGlobalRef(nullptr), nullptr); 1446 } 1447 1448 TEST_F(JniInternalTest, NewGlobalRef) { 1449 jstring s = env_->NewStringUTF(""); 1450 ASSERT_NE(s, nullptr); 1451 jobject o = env_->NewGlobalRef(s); 1452 EXPECT_NE(o, nullptr); 1453 EXPECT_NE(o, s); 1454 1455 EXPECT_EQ(env_->GetObjectRefType(o), JNIGlobalRefType); 1456 } 1457 1458 TEST_F(JniInternalTest, DeleteGlobalRef_nullptr) { 1459 env_->DeleteGlobalRef(nullptr); 1460 } 1461 1462 TEST_F(JniInternalTest, DeleteGlobalRef) { 1463 jstring s = env_->NewStringUTF(""); 1464 ASSERT_NE(s, nullptr); 1465 1466 jobject o = env_->NewGlobalRef(s); 1467 ASSERT_NE(o, nullptr); 1468 env_->DeleteGlobalRef(o); 1469 1470 // Currently, deleting an already-deleted reference is just a CheckJNI warning. 1471 { 1472 CheckJniAbortCatcher check_jni_abort_catcher; 1473 env_->DeleteGlobalRef(o); 1474 1475 std::string expected(StringPrintf("native code passing in reference to " 1476 "invalid global reference: %p", o)); 1477 check_jni_abort_catcher.Check(expected.c_str()); 1478 } 1479 1480 jobject o1 = env_->NewGlobalRef(s); 1481 ASSERT_NE(o1, nullptr); 1482 jobject o2 = env_->NewGlobalRef(s); 1483 ASSERT_NE(o2, nullptr); 1484 1485 env_->DeleteGlobalRef(o1); 1486 env_->DeleteGlobalRef(o2); 1487 } 1488 1489 TEST_F(JniInternalTest, NewWeakGlobalRef_nullptr) { 1490 EXPECT_EQ(env_->NewWeakGlobalRef(nullptr), nullptr); 1491 } 1492 1493 TEST_F(JniInternalTest, NewWeakGlobalRef) { 1494 jstring s = env_->NewStringUTF(""); 1495 ASSERT_NE(s, nullptr); 1496 jobject o = env_->NewWeakGlobalRef(s); 1497 EXPECT_NE(o, nullptr); 1498 EXPECT_NE(o, s); 1499 1500 EXPECT_EQ(env_->GetObjectRefType(o), JNIWeakGlobalRefType); 1501 } 1502 1503 TEST_F(JniInternalTest, DeleteWeakGlobalRef_nullptr) { 1504 env_->DeleteWeakGlobalRef(nullptr); 1505 } 1506 1507 TEST_F(JniInternalTest, DeleteWeakGlobalRef) { 1508 jstring s = env_->NewStringUTF(""); 1509 ASSERT_NE(s, nullptr); 1510 1511 jobject o = env_->NewWeakGlobalRef(s); 1512 ASSERT_NE(o, nullptr); 1513 env_->DeleteWeakGlobalRef(o); 1514 1515 // Currently, deleting an already-deleted reference is just a CheckJNI warning. 1516 { 1517 CheckJniAbortCatcher check_jni_abort_catcher; 1518 env_->DeleteWeakGlobalRef(o); 1519 1520 std::string expected(StringPrintf("native code passing in reference to " 1521 "invalid weak global reference: %p", o)); 1522 check_jni_abort_catcher.Check(expected.c_str()); 1523 } 1524 1525 jobject o1 = env_->NewWeakGlobalRef(s); 1526 ASSERT_NE(o1, nullptr); 1527 jobject o2 = env_->NewWeakGlobalRef(s); 1528 ASSERT_NE(o2, nullptr); 1529 1530 env_->DeleteWeakGlobalRef(o1); 1531 env_->DeleteWeakGlobalRef(o2); 1532 } 1533 1534 TEST_F(JniInternalTest, ExceptionDescribe) { 1535 // This checks how ExceptionDescribe handles call without exception. 1536 env_->ExceptionClear(); 1537 env_->ExceptionDescribe(); 1538 } 1539 1540 TEST_F(JniInternalTest, Throw) { 1541 EXPECT_EQ(JNI_ERR, env_->Throw(nullptr)); 1542 1543 jclass exception_class = env_->FindClass("java/lang/RuntimeException"); 1544 ASSERT_TRUE(exception_class != nullptr); 1545 jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class)); 1546 ASSERT_TRUE(exception != nullptr); 1547 1548 EXPECT_EQ(JNI_OK, env_->Throw(exception)); 1549 EXPECT_TRUE(env_->ExceptionCheck()); 1550 jthrowable thrown_exception = env_->ExceptionOccurred(); 1551 env_->ExceptionClear(); 1552 EXPECT_TRUE(env_->IsSameObject(exception, thrown_exception)); 1553 } 1554 1555 TEST_F(JniInternalTest, ThrowNew) { 1556 EXPECT_EQ(JNI_ERR, env_->Throw(nullptr)); 1557 1558 jclass exception_class = env_->FindClass("java/lang/RuntimeException"); 1559 ASSERT_TRUE(exception_class != nullptr); 1560 1561 jthrowable thrown_exception; 1562 1563 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, "hello world")); 1564 EXPECT_TRUE(env_->ExceptionCheck()); 1565 thrown_exception = env_->ExceptionOccurred(); 1566 env_->ExceptionClear(); 1567 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class)); 1568 1569 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, nullptr)); 1570 EXPECT_TRUE(env_->ExceptionCheck()); 1571 thrown_exception = env_->ExceptionOccurred(); 1572 env_->ExceptionClear(); 1573 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class)); 1574 } 1575 1576 TEST_F(JniInternalTest, NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity) { 1577 // Start runtime. 1578 Thread* self = Thread::Current(); 1579 self->TransitionFromSuspendedToRunnable(); 1580 MakeExecutable(nullptr, "java.lang.Class"); 1581 MakeExecutable(nullptr, "java.lang.Object"); 1582 MakeExecutable(nullptr, "java.nio.DirectByteBuffer"); 1583 MakeExecutable(nullptr, "java.nio.MemoryBlock"); 1584 MakeExecutable(nullptr, "java.nio.MemoryBlock$UnmanagedBlock"); 1585 MakeExecutable(nullptr, "java.nio.MappedByteBuffer"); 1586 MakeExecutable(nullptr, "java.nio.ByteBuffer"); 1587 MakeExecutable(nullptr, "java.nio.Buffer"); 1588 // TODO: we only load a dex file here as starting the runtime relies upon it. 1589 const char* class_name = "StaticLeafMethods"; 1590 LoadDex(class_name); 1591 bool started = runtime_->Start(); 1592 ASSERT_TRUE(started); 1593 1594 jclass buffer_class = env_->FindClass("java/nio/Buffer"); 1595 ASSERT_NE(buffer_class, nullptr); 1596 1597 char bytes[1024]; 1598 jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes)); 1599 ASSERT_NE(buffer, nullptr); 1600 ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class)); 1601 ASSERT_EQ(env_->GetDirectBufferAddress(buffer), bytes); 1602 ASSERT_EQ(env_->GetDirectBufferCapacity(buffer), static_cast<jlong>(sizeof(bytes))); 1603 1604 { 1605 CheckJniAbortCatcher check_jni_abort_catcher; 1606 env_->NewDirectByteBuffer(bytes, static_cast<jlong>(INT_MAX) + 1); 1607 check_jni_abort_catcher.Check("in call to NewDirectByteBuffer"); 1608 } 1609 } 1610 1611 TEST_F(JniInternalTest, MonitorEnterExit) { 1612 // Create an object to torture. 1613 jclass object_class = env_->FindClass("java/lang/Object"); 1614 ASSERT_NE(object_class, nullptr); 1615 jobject object = env_->AllocObject(object_class); 1616 ASSERT_NE(object, nullptr); 1617 1618 // Expected class of exceptions 1619 jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException"); 1620 ASSERT_NE(imse_class, nullptr); 1621 1622 jthrowable thrown_exception; 1623 1624 // Unlock of unowned monitor 1625 env_->MonitorExit(object); 1626 EXPECT_TRUE(env_->ExceptionCheck()); 1627 thrown_exception = env_->ExceptionOccurred(); 1628 env_->ExceptionClear(); 1629 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class)); 1630 1631 // Lock of unowned monitor 1632 env_->MonitorEnter(object); 1633 EXPECT_FALSE(env_->ExceptionCheck()); 1634 // Regular unlock 1635 env_->MonitorExit(object); 1636 EXPECT_FALSE(env_->ExceptionCheck()); 1637 1638 // Recursively lock a lot 1639 size_t max_recursive_lock = 1024; 1640 for (size_t i = 0; i < max_recursive_lock; i++) { 1641 env_->MonitorEnter(object); 1642 EXPECT_FALSE(env_->ExceptionCheck()); 1643 } 1644 // Recursively unlock a lot 1645 for (size_t i = 0; i < max_recursive_lock; i++) { 1646 env_->MonitorExit(object); 1647 EXPECT_FALSE(env_->ExceptionCheck()); 1648 } 1649 1650 // Unlock of unowned monitor 1651 env_->MonitorExit(object); 1652 EXPECT_TRUE(env_->ExceptionCheck()); 1653 thrown_exception = env_->ExceptionOccurred(); 1654 env_->ExceptionClear(); 1655 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class)); 1656 1657 // It's an error to call MonitorEnter or MonitorExit on nullptr. 1658 { 1659 CheckJniAbortCatcher check_jni_abort_catcher; 1660 env_->MonitorEnter(nullptr); 1661 check_jni_abort_catcher.Check("in call to MonitorEnter"); 1662 env_->MonitorExit(nullptr); 1663 check_jni_abort_catcher.Check("in call to MonitorExit"); 1664 } 1665 } 1666 1667 TEST_F(JniInternalTest, DetachCurrentThread) { 1668 CleanUpJniEnv(); // cleanup now so TearDown won't have junk from wrong JNIEnv 1669 jint ok = vm_->DetachCurrentThread(); 1670 EXPECT_EQ(JNI_OK, ok); 1671 1672 jint err = vm_->DetachCurrentThread(); 1673 EXPECT_EQ(JNI_ERR, err); 1674 vm_->AttachCurrentThread(&env_, nullptr); // need attached thread for CommonRuntimeTest::TearDown 1675 } 1676 1677 } // namespace art 1678