1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <pthread.h> 18 19 #include <cstdio> 20 #include <iostream> 21 #include <vector> 22 23 #include <android-base/logging.h> 24 25 #include "art_method-inl.h" 26 #include "base/runtime_debug.h" 27 #include "jni.h" 28 29 namespace art { 30 31 static JavaVM* jvm = nullptr; 32 33 static jint Java_Main_intFastNativeMethod(JNIEnv*, jclass, jint a, jint b, jint c); 34 static jint Java_Main_intCriticalNativeMethod(jint a, jint b, jint c); 35 36 static JNINativeMethod sMainMethods[] = { 37 {"intFastNativeMethod", "(III)I", reinterpret_cast<void*>(Java_Main_intFastNativeMethod) }, 38 {"intCriticalNativeMethod", "(III)I", reinterpret_cast<void*>(Java_Main_intCriticalNativeMethod) }, 39 }; 40 JNI_OnLoad(JavaVM * vm,void *)41 extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void*) { 42 CHECK(vm != nullptr); 43 CHECK(jvm == nullptr); 44 jvm = vm; 45 std::cout << "JNI_OnLoad called" << std::endl; 46 47 return JNI_VERSION_1_6; 48 } 49 JNI_OnUnload(JavaVM *,void *)50 extern "C" JNIEXPORT void JNI_OnUnload(JavaVM*, void*) { 51 // std::cout since LOG(INFO) adds extra stuff like pid. 52 std::cout << "JNI_OnUnload called" << std::endl; 53 // Clear jvm for CHECK in test 004-JniTest. 54 jvm = nullptr; 55 } 56 AttachHelper(void * arg)57 static void* AttachHelper(void* arg) { 58 CHECK(jvm != nullptr); 59 60 JNIEnv* env = nullptr; 61 JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, nullptr }; 62 int attach_result = jvm->AttachCurrentThread(&env, &args); 63 CHECK_EQ(attach_result, 0); 64 65 using Fn = void(*)(JNIEnv*); 66 Fn fn = reinterpret_cast<Fn>(arg); 67 fn(env); 68 69 int detach_result = jvm->DetachCurrentThread(); 70 CHECK_EQ(detach_result, 0); 71 return nullptr; 72 } 73 PthreadHelper(void (* fn)(JNIEnv *))74 static void PthreadHelper(void (*fn)(JNIEnv*)) { 75 pthread_t pthread; 76 int pthread_create_result = pthread_create(&pthread, nullptr, AttachHelper, 77 reinterpret_cast<void*>(fn)); 78 CHECK_EQ(pthread_create_result, 0); 79 int pthread_join_result = pthread_join(pthread, nullptr); 80 CHECK_EQ(pthread_join_result, 0); 81 } 82 testFindClassOnAttachedNativeThread(JNIEnv * env)83 static void testFindClassOnAttachedNativeThread(JNIEnv* env) { 84 jclass clazz = env->FindClass("Main"); 85 CHECK(clazz != nullptr); 86 CHECK(!env->ExceptionCheck()); 87 88 jobjectArray array = env->NewObjectArray(0, clazz, nullptr); 89 CHECK(array != nullptr); 90 CHECK(!env->ExceptionCheck()); 91 } 92 Java_Main_testUTFRegion(JNIEnv * env,jclass,jstring null_str)93 extern "C" JNIEXPORT void JNICALL Java_Main_testUTFRegion(JNIEnv* env, jclass, jstring null_str) { 94 jstring foo_str = env->NewStringUTF("FOOBAR"); 95 jstring emoji_str = env->NewStringUTF("SKI ⛷ SKI"); 96 char buf[1024]; 97 memset(buf, 'Y', sizeof(buf)); 98 buf[1023] = '\0'; 99 100 env->GetStringUTFRegion(foo_str, 3, 1, buf); 101 buf[1023] = '\0'; 102 CHECK_EQ(strcmp("B", buf), 0) << buf; 103 104 // Null char on 0 len region 105 env->GetStringUTFRegion(foo_str, 3, 0, buf); 106 buf[1023] = '\0'; 107 CHECK_EQ(strcmp("", buf), 0) << buf; 108 109 // No SEGV 110 env->GetStringUTFRegion(foo_str, 3, 0, nullptr); 111 112 env->GetStringUTFRegion(null_str, 1, 1, buf); 113 buf[1023] = '\0'; 114 std::array<uint8_t, 3> nullbuf{ 0xc0, 0x80, 0x00 }; 115 CHECK_EQ(memcmp(nullbuf.data(), buf, 3), 0); 116 117 env->GetStringUTFRegion(emoji_str, 1, 6, buf); 118 buf[1023] = '\0'; 119 CHECK_EQ(strcmp("KI ⛷ S", buf), 0); 120 } 121 Java_Main_getFieldSubclass(JNIEnv * env,jclass,jobject f_obj,jclass sub)122 extern "C" JNIEXPORT jint JNICALL Java_Main_getFieldSubclass(JNIEnv* env, 123 jclass, 124 jobject f_obj, 125 jclass sub) { 126 jfieldID f = env->FromReflectedField(f_obj); 127 return env->GetStaticIntField(sub, f); 128 } 129 130 // http://b/10994325 Java_Main_testFindClassOnAttachedNativeThread(JNIEnv *,jclass)131 extern "C" JNIEXPORT void JNICALL Java_Main_testFindClassOnAttachedNativeThread(JNIEnv*, jclass) { 132 PthreadHelper(&testFindClassOnAttachedNativeThread); 133 } 134 testFindFieldOnAttachedNativeThread(JNIEnv * env)135 static void testFindFieldOnAttachedNativeThread(JNIEnv* env) { 136 jclass clazz = env->FindClass("Main"); 137 CHECK(clazz != nullptr); 138 CHECK(!env->ExceptionCheck()); 139 140 jfieldID field = env->GetStaticFieldID(clazz, "testFindFieldOnAttachedNativeThreadField", "Z"); 141 CHECK(field != nullptr); 142 CHECK(!env->ExceptionCheck()); 143 144 env->SetStaticBooleanField(clazz, field, JNI_TRUE); 145 } 146 Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv *,jclass)147 extern "C" JNIEXPORT void JNICALL Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv*, 148 jclass) { 149 PthreadHelper(&testFindFieldOnAttachedNativeThread); 150 } 151 testReflectFieldGetFromAttachedNativeThread(JNIEnv * env)152 static void testReflectFieldGetFromAttachedNativeThread(JNIEnv* env) { 153 jclass clazz = env->FindClass("Main"); 154 CHECK(clazz != nullptr); 155 CHECK(!env->ExceptionCheck()); 156 157 jclass class_clazz = env->FindClass("java/lang/Class"); 158 CHECK(class_clazz != nullptr); 159 CHECK(!env->ExceptionCheck()); 160 161 jmethodID getFieldMetodId = env->GetMethodID(class_clazz, "getField", 162 "(Ljava/lang/String;)Ljava/lang/reflect/Field;"); 163 CHECK(getFieldMetodId != nullptr); 164 CHECK(!env->ExceptionCheck()); 165 166 jstring field_name = env->NewStringUTF("testReflectFieldGetFromAttachedNativeThreadField"); 167 CHECK(field_name != nullptr); 168 CHECK(!env->ExceptionCheck()); 169 170 jobject field = env->CallObjectMethod(clazz, getFieldMetodId, field_name); 171 CHECK(field != nullptr); 172 CHECK(!env->ExceptionCheck()); 173 174 jclass field_clazz = env->FindClass("java/lang/reflect/Field"); 175 CHECK(field_clazz != nullptr); 176 CHECK(!env->ExceptionCheck()); 177 178 jmethodID getBooleanMetodId = env->GetMethodID(field_clazz, "getBoolean", 179 "(Ljava/lang/Object;)Z"); 180 CHECK(getBooleanMetodId != nullptr); 181 CHECK(!env->ExceptionCheck()); 182 183 jboolean value = env->CallBooleanMethod(field, getBooleanMetodId, /* ignored */ clazz); 184 CHECK(value == false); 185 CHECK(!env->ExceptionCheck()); 186 } 187 188 // http://b/15539150 Java_Main_testReflectFieldGetFromAttachedNativeThreadNative(JNIEnv *,jclass)189 extern "C" JNIEXPORT void JNICALL Java_Main_testReflectFieldGetFromAttachedNativeThreadNative( 190 JNIEnv*, jclass) { 191 PthreadHelper(&testReflectFieldGetFromAttachedNativeThread); 192 } 193 194 195 // http://b/11243757 Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv * env,jclass)196 extern "C" JNIEXPORT void JNICALL Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env, 197 jclass) { 198 jclass super_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SuperClass"); 199 CHECK(super_class != nullptr); 200 201 jmethodID execute = env->GetStaticMethodID(super_class, "execute", "()V"); 202 CHECK(execute != nullptr); 203 204 jclass sub_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SubClass"); 205 CHECK(sub_class != nullptr); 206 207 env->CallStaticVoidMethod(sub_class, execute); 208 } 209 Java_Main_testGetMirandaMethodNative(JNIEnv * env,jclass)210 extern "C" JNIEXPORT jobject JNICALL Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass) { 211 jclass abstract_class = env->FindClass("Main$testGetMirandaMethod_MirandaAbstract"); 212 CHECK(abstract_class != nullptr); 213 jmethodID miranda_method = env->GetMethodID(abstract_class, "inInterface", "()Z"); 214 CHECK(miranda_method != nullptr); 215 return env->ToReflectedMethod(abstract_class, miranda_method, JNI_FALSE); 216 } 217 218 // https://code.google.com/p/android/issues/detail?id=63055 Java_Main_testZeroLengthByteBuffers(JNIEnv * env,jclass)219 extern "C" void JNICALL Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass) { 220 std::vector<uint8_t> buffer(1); 221 jobject byte_buffer = env->NewDirectByteBuffer(&buffer[0], 0); 222 CHECK(byte_buffer != nullptr); 223 CHECK(!env->ExceptionCheck()); 224 225 CHECK_EQ(env->GetDirectBufferAddress(byte_buffer), &buffer[0]); 226 CHECK_EQ(env->GetDirectBufferCapacity(byte_buffer), 0); 227 } 228 229 constexpr size_t kByteReturnSize = 7; 230 jbyte byte_returns[kByteReturnSize] = { 0, 1, 2, 127, -1, -2, -128 }; 231 Java_Main_byteMethod(JNIEnv *,jclass,jbyte b1,jbyte b2,jbyte b3,jbyte b4,jbyte b5,jbyte b6,jbyte b7,jbyte b8,jbyte b9,jbyte b10)232 extern "C" jbyte JNICALL Java_Main_byteMethod(JNIEnv*, jclass, jbyte b1, jbyte b2, 233 jbyte b3, jbyte b4, jbyte b5, jbyte b6, 234 jbyte b7, jbyte b8, jbyte b9, jbyte b10) { 235 // We use b1 to drive the output. 236 CHECK_EQ(b2, 2); 237 CHECK_EQ(b3, -3); 238 CHECK_EQ(b4, 4); 239 CHECK_EQ(b5, -5); 240 CHECK_EQ(b6, 6); 241 CHECK_EQ(b7, -7); 242 CHECK_EQ(b8, 8); 243 CHECK_EQ(b9, -9); 244 CHECK_EQ(b10, 10); 245 246 CHECK_LE(0, b1); 247 CHECK_LT(b1, static_cast<jbyte>(kByteReturnSize)); 248 249 return byte_returns[b1]; 250 } 251 252 constexpr size_t kShortReturnSize = 9; 253 jshort short_returns[kShortReturnSize] = { 0, 1, 2, 127, 32767, -1, -2, -128, 254 static_cast<jshort>(0x8000) }; 255 // The weird static_cast is because short int is only guaranteed down to -32767, not Java's -32768. 256 Java_Main_shortMethod(JNIEnv *,jclass,jshort s1,jshort s2,jshort s3,jshort s4,jshort s5,jshort s6,jshort s7,jshort s8,jshort s9,jshort s10)257 extern "C" jshort JNICALL Java_Main_shortMethod(JNIEnv*, jclass, jshort s1, jshort s2, 258 jshort s3, jshort s4, jshort s5, jshort s6, 259 jshort s7, jshort s8, jshort s9, jshort s10) { 260 // We use s1 to drive the output. 261 CHECK_EQ(s2, 2); 262 CHECK_EQ(s3, -3); 263 CHECK_EQ(s4, 4); 264 CHECK_EQ(s5, -5); 265 CHECK_EQ(s6, 6); 266 CHECK_EQ(s7, -7); 267 CHECK_EQ(s8, 8); 268 CHECK_EQ(s9, -9); 269 CHECK_EQ(s10, 10); 270 271 CHECK_LE(0, s1); 272 CHECK_LT(s1, static_cast<jshort>(kShortReturnSize)); 273 274 return short_returns[s1]; 275 } 276 Java_Main_booleanMethod(JNIEnv *,jclass,jboolean b1,jboolean b2,jboolean b3,jboolean b4,jboolean b5,jboolean b6,jboolean b7,jboolean b8,jboolean b9,jboolean b10)277 extern "C" jboolean JNICALL Java_Main_booleanMethod(JNIEnv*, jclass, jboolean b1, 278 jboolean b2, jboolean b3, jboolean b4, 279 jboolean b5, jboolean b6, jboolean b7, 280 jboolean b8, jboolean b9, jboolean b10) { 281 // We use b1 to drive the output. 282 CHECK_EQ(b2, JNI_TRUE); 283 CHECK_EQ(b3, JNI_FALSE); 284 CHECK_EQ(b4, JNI_TRUE); 285 CHECK_EQ(b5, JNI_FALSE); 286 CHECK_EQ(b6, JNI_TRUE); 287 CHECK_EQ(b7, JNI_FALSE); 288 CHECK_EQ(b8, JNI_TRUE); 289 CHECK_EQ(b9, JNI_FALSE); 290 CHECK_EQ(b10, JNI_TRUE); 291 292 CHECK(b1 == JNI_TRUE || b1 == JNI_FALSE); 293 return b1; 294 } 295 296 constexpr size_t kCharReturnSize = 8; 297 jchar char_returns[kCharReturnSize] = { 0, 1, 2, 127, 255, 256, 15000, 34000 }; 298 Java_Main_charMethod(JNIEnv *,jclass,jchar c1,jchar c2,jchar c3,jchar c4,jchar c5,jchar c6,jchar c7,jchar c8,jchar c9,jchar c10)299 extern "C" jchar JNICALL Java_Main_charMethod(JNIEnv*, jclass, jchar c1, jchar c2, 300 jchar c3, jchar c4, jchar c5, jchar c6, jchar c7, 301 jchar c8, jchar c9, jchar c10) { 302 // We use c1 to drive the output. 303 CHECK_EQ(c2, 'a'); 304 CHECK_EQ(c3, 'b'); 305 CHECK_EQ(c4, 'c'); 306 CHECK_EQ(c5, '0'); 307 CHECK_EQ(c6, '1'); 308 CHECK_EQ(c7, '2'); 309 CHECK_EQ(c8, 1234); 310 CHECK_EQ(c9, 2345); 311 CHECK_EQ(c10, 3456); 312 313 CHECK_LT(c1, static_cast<jchar>(kCharReturnSize)); 314 315 return char_returns[c1]; 316 } 317 Java_Main_removeLocalObject(JNIEnv * env,jclass,jclass o)318 extern "C" JNIEXPORT void JNICALL Java_Main_removeLocalObject(JNIEnv* env, jclass, jclass o) { 319 // Delete the arg to see if it crashes. 320 env->DeleteLocalRef(o); 321 } 322 Java_Main_nativeIsAssignableFrom(JNIEnv * env,jclass,jclass from,jclass to)323 extern "C" JNIEXPORT jboolean JNICALL Java_Main_nativeIsAssignableFrom(JNIEnv* env, jclass, 324 jclass from, jclass to) { 325 return env->IsAssignableFrom(from, to); 326 } 327 testShallowGetCallingClassLoader(JNIEnv * env)328 static void testShallowGetCallingClassLoader(JNIEnv* env) { 329 // Test direct call. 330 { 331 jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack"); 332 CHECK(vmstack_clazz != nullptr); 333 CHECK(!env->ExceptionCheck()); 334 335 jmethodID getCallingClassLoaderMethodId = env->GetStaticMethodID(vmstack_clazz, 336 "getCallingClassLoader", 337 "()Ljava/lang/ClassLoader;"); 338 CHECK(getCallingClassLoaderMethodId != nullptr); 339 CHECK(!env->ExceptionCheck()); 340 341 jobject class_loader = env->CallStaticObjectMethod(vmstack_clazz, 342 getCallingClassLoaderMethodId); 343 CHECK(class_loader == nullptr); 344 CHECK(!env->ExceptionCheck()); 345 } 346 347 // Test one-level call. Use System.loadLibrary(). 348 { 349 jclass system_clazz = env->FindClass("java/lang/System"); 350 CHECK(system_clazz != nullptr); 351 CHECK(!env->ExceptionCheck()); 352 353 jmethodID loadLibraryMethodId = env->GetStaticMethodID(system_clazz, "loadLibrary", 354 "(Ljava/lang/String;)V"); 355 CHECK(loadLibraryMethodId != nullptr); 356 CHECK(!env->ExceptionCheck()); 357 358 // Create a string object. 359 jobject library_string = env->NewStringUTF("non_existing_library"); 360 CHECK(library_string != nullptr); 361 CHECK(!env->ExceptionCheck()); 362 363 env->CallStaticVoidMethod(system_clazz, loadLibraryMethodId, library_string); 364 CHECK(env->ExceptionCheck()); 365 366 // We expect UnsatisfiedLinkError. 367 jthrowable thrown = env->ExceptionOccurred(); 368 env->ExceptionClear(); 369 370 jclass unsatisfied_link_error_clazz = env->FindClass("java/lang/UnsatisfiedLinkError"); 371 jclass thrown_class = env->GetObjectClass(thrown); 372 CHECK(env->IsSameObject(unsatisfied_link_error_clazz, thrown_class)); 373 } 374 } 375 376 // http://b/16867274 Java_Main_nativeTestShallowGetCallingClassLoader(JNIEnv *,jclass)377 extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetCallingClassLoader(JNIEnv*, 378 jclass) { 379 PthreadHelper(&testShallowGetCallingClassLoader); 380 } 381 testShallowGetStackClass2(JNIEnv * env)382 static void testShallowGetStackClass2(JNIEnv* env) { 383 jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack"); 384 CHECK(vmstack_clazz != nullptr); 385 CHECK(!env->ExceptionCheck()); 386 387 // Test direct call. 388 { 389 jmethodID getStackClass2MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass2", 390 "()Ljava/lang/Class;"); 391 CHECK(getStackClass2MethodId != nullptr); 392 CHECK(!env->ExceptionCheck()); 393 394 jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass2MethodId); 395 CHECK(caller_class == nullptr); 396 CHECK(!env->ExceptionCheck()); 397 } 398 399 // Test one-level call. Use VMStack.getStackClass1(). 400 { 401 jmethodID getStackClass1MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass1", 402 "()Ljava/lang/Class;"); 403 CHECK(getStackClass1MethodId != nullptr); 404 CHECK(!env->ExceptionCheck()); 405 406 jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass1MethodId); 407 CHECK(caller_class == nullptr); 408 CHECK(!env->ExceptionCheck()); 409 } 410 411 // For better testing we would need to compile against libcore and have a two-deep stack 412 // ourselves. 413 } 414 Java_Main_nativeTestShallowGetStackClass2(JNIEnv *,jclass)415 extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetStackClass2(JNIEnv*, jclass) { 416 PthreadHelper(&testShallowGetStackClass2); 417 } 418 419 class JniCallNonvirtualVoidMethodTest { 420 public: JniCallNonvirtualVoidMethodTest(JNIEnv * env)421 explicit JniCallNonvirtualVoidMethodTest(JNIEnv* env) 422 : env_(env), 423 check_jni_ri_(true), 424 check_jni_android_(true), 425 super_(GetClass("JniCallNonvirtualTest")), 426 sub_(GetClass("JniCallNonvirtualTestSubclass")), 427 super_constructor_(GetMethodID(super_, true, "<init>")), 428 super_static_(GetMethodID(super_, false, "staticMethod")), 429 super_nonstatic_(GetMethodID(super_, true, "nonstaticMethod")), 430 sub_constructor_(GetMethodID(sub_, true, "<init>")), 431 sub_static_(GetMethodID(sub_, false, "staticMethod")), 432 sub_nonstatic_(GetMethodID(sub_, true, "nonstaticMethod")), 433 super_field_(GetFieldID(super_, "nonstaticMethodSuperCalled")), 434 sub_field_(GetFieldID(super_, "nonstaticMethodSubCalled")) {} 435 Test()436 void Test() { 437 TestStaticCallNonvirtualMethod(); 438 TestNewObject(); 439 TestnonstaticCallNonvirtualMethod(); 440 } 441 442 JNIEnv* const env_; 443 444 bool const check_jni_ri_; 445 bool const check_jni_android_; 446 447 jclass const super_; 448 jclass const sub_; 449 450 jmethodID const super_constructor_; 451 jmethodID const super_static_; 452 jmethodID const super_nonstatic_; 453 jmethodID const sub_constructor_; 454 jmethodID const sub_static_; 455 jmethodID const sub_nonstatic_; 456 457 jfieldID const super_field_; 458 jfieldID const sub_field_; 459 460 private: GetClass(const char * class_name)461 jclass GetClass(const char* class_name) { 462 jclass c = env_->FindClass(class_name); 463 if (env_->ExceptionCheck()) { 464 env_->ExceptionDescribe(); 465 env_->FatalError(__FUNCTION__); 466 } 467 CHECK(!env_->ExceptionCheck()); 468 CHECK(c != nullptr); 469 return c; 470 } 471 GetMethodID(jclass c,bool nonstatic,const char * method_name)472 jmethodID GetMethodID(jclass c, bool nonstatic, const char* method_name) { 473 jmethodID m = ((nonstatic) ? 474 env_->GetMethodID(c, method_name, "()V") : 475 env_->GetStaticMethodID(c, method_name, "()V")); 476 if (env_->ExceptionCheck()) { 477 env_->ExceptionDescribe(); 478 env_->FatalError(__FUNCTION__); 479 } 480 CHECK(m != nullptr); 481 return m; 482 } 483 CallConstructor(jclass c,jmethodID m)484 jobject CallConstructor(jclass c, jmethodID m) { 485 jobject o = env_->NewObject(c, m); 486 if (env_->ExceptionCheck()) { 487 env_->ExceptionDescribe(); 488 env_->FatalError(__FUNCTION__); 489 } 490 CHECK(o != nullptr); 491 return o; 492 } 493 CallMethod(jobject o,jclass c,jmethodID m,bool nonstatic,const char * test_case)494 void CallMethod(jobject o, jclass c, jmethodID m, bool nonstatic, const char* test_case) { 495 printf("RUNNING %s\n", test_case); 496 env_->CallNonvirtualVoidMethod(o, c, m); 497 bool exception_check = env_->ExceptionCheck(); 498 if (c == nullptr || !nonstatic) { 499 if (!exception_check) { 500 printf("FAILED %s due to missing exception\n", test_case); 501 env_->FatalError("Expected NullPointerException with null jclass"); 502 } 503 env_->ExceptionClear(); 504 } else if (exception_check) { 505 printf("FAILED %s due to pending exception\n", test_case); 506 env_->ExceptionDescribe(); 507 env_->FatalError(test_case); 508 } 509 printf("PASSED %s\n", test_case); 510 } 511 GetFieldID(jclass c,const char * field_name)512 jfieldID GetFieldID(jclass c, const char* field_name) { 513 jfieldID m = env_->GetFieldID(c, field_name, "Z"); 514 if (env_->ExceptionCheck()) { 515 env_->ExceptionDescribe(); 516 env_->FatalError(__FUNCTION__); 517 } 518 CHECK(m != nullptr); 519 return m; 520 } 521 GetBooleanField(jobject o,jfieldID f)522 jboolean GetBooleanField(jobject o, jfieldID f) { 523 jboolean b = env_->GetBooleanField(o, f); 524 if (env_->ExceptionCheck()) { 525 env_->ExceptionDescribe(); 526 env_->FatalError(__FUNCTION__); 527 } 528 return b; 529 } 530 TestStaticCallNonvirtualMethod()531 void TestStaticCallNonvirtualMethod() { 532 if (!check_jni_ri_&& !check_jni_android_) { 533 CallMethod(nullptr, nullptr, super_static_, false, "null object, null class, super static"); 534 } 535 if (!check_jni_android_) { 536 CallMethod(nullptr, super_, super_static_, false, "null object, super class, super static"); 537 } 538 if (!check_jni_android_) { 539 CallMethod(nullptr, sub_, super_static_, false, "null object, sub class, super static"); 540 } 541 542 if (!check_jni_ri_ && !check_jni_android_) { 543 CallMethod(nullptr, nullptr, sub_static_, false, "null object, null class, sub static"); 544 } 545 if (!check_jni_android_) { 546 CallMethod(nullptr, sub_, sub_static_, false, "null object, super class, sub static"); 547 } 548 if (!check_jni_android_) { 549 CallMethod(nullptr, super_, sub_static_, false, "null object, super class, sub static"); 550 } 551 } 552 TestNewObject()553 void TestNewObject() { 554 jobject super_super = CallConstructor(super_, super_constructor_); 555 jobject super_sub = CallConstructor(super_, sub_constructor_); 556 jobject sub_super = CallConstructor(sub_, super_constructor_); 557 jobject sub_sub = CallConstructor(sub_, sub_constructor_); 558 559 CHECK(env_->IsInstanceOf(super_super, super_)); 560 CHECK(!env_->IsInstanceOf(super_super, sub_)); 561 562 // Note that even though we called (and ran) the subclass 563 // constructor, we are not the subclass. 564 CHECK(env_->IsInstanceOf(super_sub, super_)); 565 CHECK(!env_->IsInstanceOf(super_sub, sub_)); 566 567 // Note that even though we called the superclass constructor, we 568 // are still the subclass. 569 CHECK(env_->IsInstanceOf(sub_super, super_)); 570 CHECK(env_->IsInstanceOf(sub_super, sub_)); 571 572 CHECK(env_->IsInstanceOf(sub_sub, super_)); 573 CHECK(env_->IsInstanceOf(sub_sub, sub_)); 574 } 575 TestnonstaticCallNonvirtualMethod(bool super_object,bool super_class,bool super_method,const char * test_case)576 void TestnonstaticCallNonvirtualMethod(bool super_object, bool super_class, bool super_method, const char* test_case) { 577 if (check_jni_android_) { 578 if (super_object && !super_method) { 579 return; // We don't allow a call with sub class method on the super class instance. 580 } 581 if (super_class && !super_method) { 582 return; // We don't allow a call with the sub class method with the super class argument. 583 } 584 } 585 jobject o = ((super_object) ? 586 CallConstructor(super_, super_constructor_) : 587 CallConstructor(sub_, sub_constructor_)); 588 jclass c = (super_class) ? super_ : sub_; 589 jmethodID m = (super_method) ? super_nonstatic_ : sub_nonstatic_; 590 CallMethod(o, c, m, true, test_case); 591 jboolean super_field = GetBooleanField(o, super_field_); 592 jboolean sub_field = GetBooleanField(o, sub_field_); 593 CHECK_EQ(super_field, super_method); 594 CHECK_NE(sub_field, super_method); 595 } 596 TestnonstaticCallNonvirtualMethod()597 void TestnonstaticCallNonvirtualMethod() { 598 TestnonstaticCallNonvirtualMethod(true, true, true, "super object, super class, super nonstatic"); 599 TestnonstaticCallNonvirtualMethod(true, false, true, "super object, sub class, super nonstatic"); 600 TestnonstaticCallNonvirtualMethod(true, false, false, "super object, sub class, sub nonstatic"); 601 TestnonstaticCallNonvirtualMethod(true, true, false, "super object, super class, sub nonstatic"); 602 603 TestnonstaticCallNonvirtualMethod(false, true, true, "sub object, super class, super nonstatic"); 604 TestnonstaticCallNonvirtualMethod(false, false, true, "sub object, sub class, super nonstatic"); 605 TestnonstaticCallNonvirtualMethod(false, false, false, "sub object, sub class, sub nonstatic"); 606 TestnonstaticCallNonvirtualMethod(false, true, false, "sub object, super class, sub nonstatic"); 607 } 608 }; 609 Java_Main_testCallNonvirtual(JNIEnv * env,jclass)610 extern "C" void JNICALL Java_Main_testCallNonvirtual(JNIEnv* env, jclass) { 611 JniCallNonvirtualVoidMethodTest(env).Test(); 612 } 613 Java_Main_testNewStringObject(JNIEnv * env,jclass)614 extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jclass) { 615 jclass c = env->FindClass("java/lang/String"); 616 CHECK(c != nullptr); 617 618 jmethodID mid1 = env->GetMethodID(c, "<init>", "()V"); 619 CHECK(mid1 != nullptr); 620 CHECK(!env->ExceptionCheck()); 621 jmethodID mid2 = env->GetMethodID(c, "<init>", "([B)V"); 622 CHECK(mid2 != nullptr); 623 CHECK(!env->ExceptionCheck()); 624 jmethodID mid3 = env->GetMethodID(c, "<init>", "([C)V"); 625 CHECK(mid3 != nullptr); 626 CHECK(!env->ExceptionCheck()); 627 jmethodID mid4 = env->GetMethodID(c, "<init>", "(Ljava/lang/String;)V"); 628 CHECK(mid4 != nullptr); 629 CHECK(!env->ExceptionCheck()); 630 631 const char* test_array = "Test"; 632 int byte_array_length = strlen(test_array); 633 jbyteArray byte_array = env->NewByteArray(byte_array_length); 634 env->SetByteArrayRegion(byte_array, 0, byte_array_length, reinterpret_cast<const jbyte*>(test_array)); 635 636 // Test NewObject 637 jstring s = reinterpret_cast<jstring>(env->NewObject(c, mid2, byte_array)); 638 CHECK(s != nullptr); 639 CHECK_EQ(env->GetStringLength(s), byte_array_length); 640 CHECK_EQ(env->GetStringUTFLength(s), byte_array_length); 641 const char* chars = env->GetStringUTFChars(s, nullptr); 642 CHECK_EQ(strcmp(test_array, chars), 0); 643 env->ReleaseStringUTFChars(s, chars); 644 645 // Test AllocObject and Call(Nonvirtual)VoidMethod 646 jstring s1 = reinterpret_cast<jstring>(env->AllocObject(c)); 647 CHECK(s1 != nullptr); 648 jstring s2 = reinterpret_cast<jstring>(env->AllocObject(c)); 649 CHECK(s2 != nullptr); 650 jstring s3 = reinterpret_cast<jstring>(env->AllocObject(c)); 651 CHECK(s3 != nullptr); 652 jstring s4 = reinterpret_cast<jstring>(env->AllocObject(c)); 653 CHECK(s4 != nullptr); 654 655 jcharArray char_array = env->NewCharArray(5); 656 jstring string_arg = env->NewStringUTF("helloworld"); 657 658 // With Var Args 659 env->CallVoidMethod(s1, mid1); 660 env->CallNonvirtualVoidMethod(s2, c, mid2, byte_array); 661 662 // With JValues 663 jvalue args3[1]; 664 args3[0].l = char_array; 665 jvalue args4[1]; 666 args4[0].l = string_arg; 667 env->CallVoidMethodA(s3, mid3, args3); 668 env->CallNonvirtualVoidMethodA(s4, c, mid4, args4); 669 670 // Test with global and weak global references 671 jstring s5 = reinterpret_cast<jstring>(env->AllocObject(c)); 672 CHECK(s5 != nullptr); 673 s5 = reinterpret_cast<jstring>(env->NewGlobalRef(s5)); 674 jstring s6 = reinterpret_cast<jstring>(env->AllocObject(c)); 675 CHECK(s6 != nullptr); 676 s6 = reinterpret_cast<jstring>(env->NewWeakGlobalRef(s6)); 677 678 env->CallVoidMethod(s5, mid1); 679 env->CallNonvirtualVoidMethod(s6, c, mid2, byte_array); 680 CHECK_EQ(env->GetStringLength(s5), 0); 681 CHECK_EQ(env->GetStringLength(s6), byte_array_length); 682 const char* chars6 = env->GetStringUTFChars(s6, nullptr); 683 CHECK_EQ(strcmp(test_array, chars6), 0); 684 env->ReleaseStringUTFChars(s6, chars6); 685 } 686 Java_Main_testGetMethodID(JNIEnv * env,jclass,jclass c)687 extern "C" JNIEXPORT jlong JNICALL Java_Main_testGetMethodID(JNIEnv* env, jclass, jclass c) { 688 return reinterpret_cast<jlong>(env->GetMethodID(c, "a", "()V")); 689 } 690 Java_Main_enterJniCriticalSection(JNIEnv * env,jclass,jint arraySize,jbyteArray array0,jbyteArray array1)691 extern "C" JNIEXPORT void JNICALL Java_Main_enterJniCriticalSection(JNIEnv* env, jclass, 692 jint arraySize, 693 jbyteArray array0, 694 jbyteArray array1) { 695 for (int i = 0; i < 50000; ++i) { 696 char* data0 = reinterpret_cast<char*>(env->GetPrimitiveArrayCritical(array0, nullptr)); 697 char* data1 = reinterpret_cast<char*>(env->GetPrimitiveArrayCritical(array1, nullptr)); 698 bool up = i % 2 == 0; 699 for (int j = 0; j < arraySize; ++j) { 700 if (up) { 701 data1[j] = data0[j] + 1; 702 } else { 703 data0[j] = data1[j] + 1; 704 } 705 } 706 env->ReleasePrimitiveArrayCritical(array1, data1, 0); 707 env->ReleasePrimitiveArrayCritical(array0, data0, 0); 708 } 709 } 710 711 class JniCallDefaultMethodsTest { 712 public: JniCallDefaultMethodsTest(JNIEnv * env)713 explicit JniCallDefaultMethodsTest(JNIEnv* env) 714 : env_(env), concrete_class_(env_->FindClass("ConcreteClass")) { 715 CHECK(!env_->ExceptionCheck()); 716 CHECK(concrete_class_ != nullptr); 717 } 718 Test()719 void Test() { 720 TestCalls("ConcreteClass", { "JniCallNonOverridenDefaultMethod", 721 "JniCallOverridenDefaultMethod", 722 "JniCallOverridenDefaultMethodWithSuper", 723 "JniCallOverridenAbstractMethod", 724 "JniCallConflictDefaultMethod", 725 "JniCallSoftConflictMethod" }); 726 TestCalls("DefaultInterface", { "JniCallNonOverridenDefaultMethod", 727 "JniCallOverridenDefaultMethod", 728 "JniCallOverridenAbstractMethod", 729 "JniCallConflictDefaultMethod", 730 "JniCallSoftConflictMethod" }); 731 TestCalls("AbstractInterface", { "JniCallSoftConflictMethod" }); 732 TestCalls("ConflictInterface", { "JniCallConflictDefaultMethod" }); 733 } 734 735 private: TestCalls(const char * declaring_class,const std::vector<const char * > & methods)736 void TestCalls(const char* declaring_class, const std::vector<const char*>& methods) { 737 jmethodID new_method = env_->GetMethodID(concrete_class_, "<init>", "()V"); 738 jobject obj = env_->NewObject(concrete_class_, new_method); 739 CHECK(!env_->ExceptionCheck()); 740 CHECK(obj != nullptr); 741 jclass decl_class = env_->FindClass(declaring_class); 742 CHECK(!env_->ExceptionCheck()); 743 CHECK(decl_class != nullptr); 744 for (const char* method : methods) { 745 jmethodID method_id = env_->GetMethodID(decl_class, method, "()V"); 746 CHECK(!env_->ExceptionCheck()); 747 printf("Calling method %s->%s on object of type ConcreteClass\n", declaring_class, method); 748 env_->CallVoidMethod(obj, method_id); 749 if (env_->ExceptionCheck()) { 750 jthrowable thrown = env_->ExceptionOccurred(); 751 env_->ExceptionClear(); 752 jmethodID to_string = env_->GetMethodID( 753 env_->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;"); 754 jstring exception_string = (jstring) env_->CallObjectMethod(thrown, to_string); 755 CHECK(!env_->ExceptionCheck()); 756 const char* exception_string_utf8 = env_->GetStringUTFChars(exception_string, nullptr); 757 CHECK(!env_->ExceptionCheck()); 758 CHECK(exception_string_utf8 != nullptr); 759 printf("EXCEPTION OCCURED: %s\n", exception_string_utf8); 760 env_->ReleaseStringUTFChars(exception_string, exception_string_utf8); 761 } 762 } 763 } 764 765 JNIEnv* env_; 766 jclass concrete_class_; 767 }; 768 Java_Main_testCallDefaultMethods(JNIEnv * env)769 extern "C" JNIEXPORT void JNICALL Java_Main_testCallDefaultMethods(JNIEnv* env) { 770 JniCallDefaultMethodsTest(env).Test(); 771 } 772 InvokeSpecificMethod(JNIEnv * env,jobject obj,const char * method)773 static void InvokeSpecificMethod(JNIEnv* env, jobject obj, const char* method) { 774 jclass lambda_class = env->FindClass("LambdaInterface"); 775 CHECK(!env->ExceptionCheck()); 776 CHECK(lambda_class != nullptr); 777 jmethodID method_id = env->GetMethodID(lambda_class, method, "()V"); 778 CHECK(!env->ExceptionCheck()); 779 env->CallVoidMethod(obj, method_id); 780 CHECK(!env->ExceptionCheck()); 781 } 782 Java_Main_testInvokeLambdaDefaultMethod(JNIEnv * e,jclass,jobject l)783 extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaDefaultMethod( 784 JNIEnv* e, jclass, jobject l) { 785 InvokeSpecificMethod(e, l, "sayHiTwice"); 786 } 787 Java_Main_testInvokeLambdaMethod(JNIEnv * e,jclass,jobject l)788 extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaMethod(JNIEnv* e, jclass, jobject l) { 789 InvokeSpecificMethod(e, l, "sayHi"); 790 } 791 792 // Register on-demand because many tests share this JNI library and 793 // we can't unconditionally register them. Java_Main_registerNativesJniTest(JNIEnv * e,jclass kls)794 extern "C" JNIEXPORT jboolean JNICALL Java_Main_registerNativesJniTest(JNIEnv* e, jclass kls) { 795 const size_t numMethods = sizeof(sMainMethods)/sizeof(JNINativeMethod); 796 797 if (e->RegisterNatives(kls, sMainMethods, numMethods) < 0) { 798 std::cerr << "RegisterNatives failed for 'Main'" << std::endl; 799 return JNI_FALSE; 800 } 801 802 return JNI_TRUE; 803 } 804 805 // Annotated with @FastNative in Java code. Doesn't need to be explicitly registered with "!". 806 // NOTE: Has to be registered explicitly to avoid mutator lock check failures. Java_Main_intFastNativeMethod(JNIEnv *,jclass,jint a,jint b,jint c)807 static jint Java_Main_intFastNativeMethod(JNIEnv*, jclass, jint a, jint b, jint c) { 808 return a + b + c; 809 } 810 811 // Annotated with @CriticalNative in Java code. Doesn't need to be explicitly registered with "!". 812 // NOTE: Has to be registered explicitly to avoid mutator lock check failures. Java_Main_intCriticalNativeMethod(jint a,jint b,jint c)813 static jint Java_Main_intCriticalNativeMethod(jint a, jint b, jint c) { 814 // Note that unlike a "Fast Native" method this excludes JNIEnv and the jclass parameters. 815 return a + b + c; 816 } 817 Java_Main_lookupClinit(JNIEnv * env,jclass,jclass kls)818 extern "C" JNIEXPORT jobject JNICALL Java_Main_lookupClinit(JNIEnv* env, jclass, jclass kls) { 819 jmethodID clinit_id = env->GetStaticMethodID(kls, "<clinit>", "()V"); 820 821 if (clinit_id != nullptr) { 822 jobject obj = env->ToReflectedMethod(kls, clinit_id, /*isStatic*/ true); 823 CHECK(obj != nullptr); 824 return obj; 825 } else { 826 return nullptr; 827 } 828 } 829 Java_Main_isSlowDebug(JNIEnv *,jclass)830 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isSlowDebug(JNIEnv*, jclass) { 831 // Return whether slow-debug is on. Only relevant for debug builds. 832 if (kIsDebugBuild) { 833 // Register a fake flag and get the default value it should be initialized with. 834 static bool fake_flag = false; 835 fake_flag = RegisterRuntimeDebugFlag(&fake_flag); 836 837 return fake_flag ? JNI_TRUE : JNI_FALSE; 838 } 839 // To pass the Java-side test, just so "on" for release builds. 840 return JNI_TRUE; 841 } 842 843 } // namespace art 844 845