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