Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2008 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 "check_jni.h"
     18 
     19 #include <iomanip>
     20 #include <sys/mman.h>
     21 #include <zlib.h>
     22 
     23 #include "android-base/stringprintf.h"
     24 
     25 #include "art_field-inl.h"
     26 #include "art_method-inl.h"
     27 #include "base/logging.h"
     28 #include "base/to_str.h"
     29 #include "class_linker.h"
     30 #include "class_linker-inl.h"
     31 #include "dex_file-inl.h"
     32 #include "gc/space/space.h"
     33 #include "java_vm_ext.h"
     34 #include "jni_internal.h"
     35 #include "mirror/class-inl.h"
     36 #include "mirror/object-inl.h"
     37 #include "mirror/object_array-inl.h"
     38 #include "mirror/string-inl.h"
     39 #include "mirror/throwable.h"
     40 #include "runtime.h"
     41 #include "scoped_thread_state_change-inl.h"
     42 #include "thread.h"
     43 #include "well_known_classes.h"
     44 
     45 namespace art {
     46 
     47 using android::base::StringAppendF;
     48 using android::base::StringPrintf;
     49 
     50 /*
     51  * ===========================================================================
     52  *      JNI function helpers
     53  * ===========================================================================
     54  */
     55 
     56 // Flags passed into ScopedCheck.
     57 #define kFlag_Default       0x0000
     58 
     59 #define kFlag_CritBad       0x0000      // Calling while in critical is not allowed.
     60 #define kFlag_CritOkay      0x0001      // Calling while in critical is allowed.
     61 #define kFlag_CritGet       0x0002      // This is a critical "get".
     62 #define kFlag_CritRelease   0x0003      // This is a critical "release".
     63 #define kFlag_CritMask      0x0003      // Bit mask to get "crit" value.
     64 
     65 #define kFlag_ExcepBad      0x0000      // Raised exceptions are not allowed.
     66 #define kFlag_ExcepOkay     0x0004      // Raised exceptions are allowed.
     67 
     68 #define kFlag_Release       0x0010      // Are we in a non-critical release function?
     69 #define kFlag_NullableUtf   0x0020      // Are our UTF parameters nullable?
     70 
     71 #define kFlag_Invocation    0x8000      // Part of the invocation interface (JavaVM*).
     72 
     73 #define kFlag_ForceTrace    0x80000000  // Add this to a JNI function's flags if you want to trace every call.
     74 
     75 class VarArgs;
     76 /*
     77  * Java primitive types:
     78  * B - jbyte
     79  * C - jchar
     80  * D - jdouble
     81  * F - jfloat
     82  * I - jint
     83  * J - jlong
     84  * S - jshort
     85  * Z - jboolean (shown as true and false)
     86  * V - void
     87  *
     88  * Java reference types:
     89  * L - jobject
     90  * a - jarray
     91  * c - jclass
     92  * s - jstring
     93  * t - jthrowable
     94  *
     95  * JNI types:
     96  * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
     97  * f - jfieldID
     98  * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
     99  * m - jmethodID
    100  * p - void*
    101  * r - jint (for release mode arguments)
    102  * u - const char* (Modified UTF-8)
    103  * z - jsize (for lengths; use i if negative values are okay)
    104  * v - JavaVM*
    105  * w - jobjectRefType
    106  * E - JNIEnv*
    107  * . - no argument; just print "..." (used for varargs JNI calls)
    108  *
    109  */
    110 union JniValueType {
    111   jarray a;
    112   jboolean b;
    113   jclass c;
    114   jfieldID f;
    115   jint i;
    116   jmethodID m;
    117   const void* p;  // Pointer.
    118   jint r;  // Release mode.
    119   jstring s;
    120   jthrowable t;
    121   const char* u;  // Modified UTF-8.
    122   JavaVM* v;
    123   jobjectRefType w;
    124   jsize z;
    125   jbyte B;
    126   jchar C;
    127   jdouble D;
    128   JNIEnv* E;
    129   jfloat F;
    130   jint I;
    131   jlong J;
    132   jobject L;
    133   jshort S;
    134   const void* V;  // void
    135   jboolean Z;
    136   const VarArgs* va;
    137 };
    138 
    139 /*
    140  * A structure containing all the information needed to validate varargs arguments.
    141  *
    142  * Note that actually getting the arguments from this structure mutates it so should only be done on
    143  * owned copies.
    144  */
    145 class VarArgs {
    146  public:
    147   VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
    148     va_copy(vargs_, var);
    149   }
    150 
    151   VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
    152 
    153   ~VarArgs() {
    154     if (type_ == kTypeVaList) {
    155       va_end(vargs_);
    156     }
    157   }
    158 
    159   VarArgs(VarArgs&& other) {
    160     m_ = other.m_;
    161     cnt_ = other.cnt_;
    162     type_ = other.type_;
    163     if (other.type_ == kTypeVaList) {
    164       va_copy(vargs_, other.vargs_);
    165     } else {
    166       ptr_ = other.ptr_;
    167     }
    168   }
    169 
    170   // This method is const because we need to ensure that one only uses the GetValue method on an
    171   // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
    172   // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
    173   // we want to use one we need to Clone() it.
    174   VarArgs Clone() const {
    175     if (type_ == kTypeVaList) {
    176       // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
    177       // messed up if the source argument is not the exact type 'va_list'.
    178       return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
    179     } else {
    180       return VarArgs(m_, cnt_, ptr_);
    181     }
    182   }
    183 
    184   jmethodID GetMethodID() const {
    185     return m_;
    186   }
    187 
    188   JniValueType GetValue(char fmt) {
    189     JniValueType o;
    190     if (type_ == kTypeVaList) {
    191       switch (fmt) {
    192         case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break;
    193         case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break;
    194         case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break;
    195         case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break;
    196         case 'I': o.I = va_arg(vargs_, jint); break;
    197         case 'J': o.J = va_arg(vargs_, jlong); break;
    198         case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
    199         case 'D': o.D = va_arg(vargs_, jdouble); break;
    200         case 'L': o.L = va_arg(vargs_, jobject); break;
    201         default:
    202           LOG(FATAL) << "Illegal type format char " << fmt;
    203           UNREACHABLE();
    204       }
    205     } else {
    206       CHECK(type_ == kTypePtr);
    207       jvalue v = ptr_[cnt_];
    208       cnt_++;
    209       switch (fmt) {
    210         case 'Z': o.Z = v.z; break;
    211         case 'B': o.B = v.b; break;
    212         case 'C': o.C = v.c; break;
    213         case 'S': o.S = v.s; break;
    214         case 'I': o.I = v.i; break;
    215         case 'J': o.J = v.j; break;
    216         case 'F': o.F = v.f; break;
    217         case 'D': o.D = v.d; break;
    218         case 'L': o.L = v.l; break;
    219         default:
    220           LOG(FATAL) << "Illegal type format char " << fmt;
    221           UNREACHABLE();
    222       }
    223     }
    224     return o;
    225   }
    226 
    227  private:
    228   VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
    229     va_copy(vargs_, var);
    230   }
    231 
    232   VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
    233 
    234   enum VarArgsType {
    235     kTypeVaList,
    236     kTypePtr,
    237   };
    238 
    239   jmethodID m_;
    240   VarArgsType type_;
    241   uint32_t cnt_;
    242   union {
    243     va_list vargs_;
    244     const jvalue* ptr_;
    245   };
    246 };
    247 
    248 class ScopedCheck {
    249  public:
    250   ScopedCheck(int flags, const char* functionName, bool has_method = true)
    251       : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
    252   }
    253 
    254   ~ScopedCheck() {}
    255 
    256   // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
    257   // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
    258   // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
    259   // circumstances, but this is incorrect.
    260   bool CheckClassName(const char* class_name) {
    261     if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
    262       AbortF("illegal class name '%s'\n"
    263              "    (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
    264              class_name);
    265       return false;
    266     }
    267     return true;
    268   }
    269 
    270   /*
    271    * Verify that this instance field ID is valid for this object.
    272    *
    273    * Assumes "jobj" has already been validated.
    274    */
    275   bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
    276       REQUIRES_SHARED(Locks::mutator_lock_) {
    277     ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
    278     if (o == nullptr) {
    279       AbortF("field operation on NULL object: %p", java_object);
    280       return false;
    281     }
    282     if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
    283       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
    284       AbortF("field operation on invalid %s: %p",
    285              GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
    286              java_object);
    287       return false;
    288     }
    289 
    290     ArtField* f = CheckFieldID(fid);
    291     if (f == nullptr) {
    292       return false;
    293     }
    294     mirror::Class* c = o->GetClass();
    295     if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
    296       AbortF("jfieldID %s not valid for an object of class %s",
    297              f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
    298       return false;
    299     }
    300     return true;
    301   }
    302 
    303   /*
    304    * Verify that the pointer value is non-null.
    305    */
    306   bool CheckNonNull(const void* ptr) {
    307     if (UNLIKELY(ptr == nullptr)) {
    308       AbortF("non-nullable argument was NULL");
    309       return false;
    310     }
    311     return true;
    312   }
    313 
    314   /*
    315    * Verify that the method's return type matches the type of call.
    316    * 'expectedType' will be "L" for all objects, including arrays.
    317    */
    318   bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
    319                          jmethodID mid, Primitive::Type type, InvokeType invoke)
    320       REQUIRES_SHARED(Locks::mutator_lock_) {
    321     ArtMethod* m = CheckMethodID(mid);
    322     if (m == nullptr) {
    323       return false;
    324     }
    325     if (type != Primitive::GetType(m->GetShorty()[0])) {
    326       AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
    327       return false;
    328     }
    329     bool is_static = (invoke == kStatic);
    330     if (is_static != m->IsStatic()) {
    331       if (is_static) {
    332         AbortF("calling non-static method %s with %s",
    333                m->PrettyMethod().c_str(), function_name_);
    334       } else {
    335         AbortF("calling static method %s with %s",
    336                m->PrettyMethod().c_str(), function_name_);
    337       }
    338       return false;
    339     }
    340     if (invoke != kVirtual) {
    341       ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
    342       if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
    343         AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
    344             m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
    345         return false;
    346       }
    347     }
    348     if (invoke != kStatic) {
    349       ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
    350       if (o == nullptr) {
    351         AbortF("can't call %s on null object", m->PrettyMethod().c_str());
    352         return false;
    353       } else if (!o->InstanceOf(m->GetDeclaringClass())) {
    354         AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
    355                o->PrettyTypeOf().c_str());
    356         return false;
    357       }
    358     }
    359     return true;
    360   }
    361 
    362   /*
    363    * Verify that this static field ID is valid for this class.
    364    *
    365    * Assumes "java_class" has already been validated.
    366    */
    367   bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
    368       REQUIRES_SHARED(Locks::mutator_lock_) {
    369     ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
    370     ArtField* f = CheckFieldID(fid);
    371     if (f == nullptr) {
    372       return false;
    373     }
    374     if (c != f->GetDeclaringClass()) {
    375       AbortF("static jfieldID %p not valid for class %s", fid,
    376              mirror::Class::PrettyClass(c).c_str());
    377       return false;
    378     }
    379     return true;
    380   }
    381 
    382   /*
    383    * Verify that "mid" is appropriate for "java_class".
    384    *
    385    * A mismatch isn't dangerous, because the jmethodID defines the class.  In
    386    * fact, java_class is unused in the implementation.  It's best if we don't
    387    * allow bad code in the system though.
    388    *
    389    * Instances of "java_class" must be instances of the method's declaring class.
    390    */
    391   bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
    392       REQUIRES_SHARED(Locks::mutator_lock_) {
    393     ArtMethod* m = CheckMethodID(mid);
    394     if (m == nullptr) {
    395       return false;
    396     }
    397     ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
    398     if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
    399       AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
    400              mirror::Class::PrettyClass(c).c_str());
    401       return false;
    402     }
    403     return true;
    404   }
    405 
    406   /*
    407    * Verify that "mid" is appropriate for "jobj".
    408    *
    409    * Make sure the object is an instance of the method's declaring class.
    410    * (Note the mid might point to a declaration in an interface; this
    411    * will be handled automatically by the instanceof check.)
    412    */
    413   bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
    414       REQUIRES_SHARED(Locks::mutator_lock_) {
    415     ArtMethod* m = CheckMethodID(mid);
    416     if (m == nullptr) {
    417       return false;
    418     }
    419     ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
    420     if (o == nullptr) {
    421       AbortF("can't call %s on null object", m->PrettyMethod().c_str());
    422       return false;
    423     } else if (!o->InstanceOf(m->GetDeclaringClass())) {
    424       AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
    425              o->PrettyTypeOf().c_str());
    426       return false;
    427     }
    428     return true;
    429   }
    430 
    431   /**
    432    * The format string is a sequence of the following characters,
    433    * and must be followed by arguments of the corresponding types
    434    * in the same order.
    435    *
    436    * Java primitive types:
    437    * B - jbyte
    438    * C - jchar
    439    * D - jdouble
    440    * F - jfloat
    441    * I - jint
    442    * J - jlong
    443    * S - jshort
    444    * Z - jboolean (shown as true and false)
    445    * V - void
    446    *
    447    * Java reference types:
    448    * L - jobject
    449    * a - jarray
    450    * c - jclass
    451    * s - jstring
    452    *
    453    * JNI types:
    454    * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
    455    * f - jfieldID
    456    * m - jmethodID
    457    * p - void*
    458    * r - jint (for release mode arguments)
    459    * u - const char* (Modified UTF-8)
    460    * z - jsize (for lengths; use i if negative values are okay)
    461    * v - JavaVM*
    462    * E - JNIEnv*
    463    * . - VarArgs* for Jni calls with variable length arguments
    464    *
    465    * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
    466    */
    467   bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
    468       REQUIRES_SHARED(Locks::mutator_lock_) {
    469     ArtMethod* traceMethod = nullptr;
    470     if (has_method_ && soa.Vm()->IsTracingEnabled()) {
    471       // We need to guard some of the invocation interface's calls: a bad caller might
    472       // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
    473       Thread* self = Thread::Current();
    474       if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
    475         traceMethod = self->GetCurrentMethod(nullptr);
    476       }
    477     }
    478 
    479     if (((flags_ & kFlag_ForceTrace) != 0) ||
    480         (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
    481       std::string msg;
    482       for (size_t i = 0; fmt[i] != '\0'; ++i) {
    483         TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
    484         if (fmt[i + 1] != '\0') {
    485           StringAppendF(&msg, ", ");
    486         }
    487       }
    488 
    489       if ((flags_ & kFlag_ForceTrace) != 0) {
    490         LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
    491       } else if (entry) {
    492         if (has_method_) {
    493           std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
    494           LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
    495           indent_ = methodName.size() + 1;
    496         } else {
    497           LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
    498           indent_ = 0;
    499         }
    500       } else {
    501         LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
    502       }
    503     }
    504 
    505     // We always do the thorough checks on entry, and never on exit...
    506     if (entry) {
    507       for (size_t i = 0; fmt[i] != '\0'; ++i) {
    508         if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
    509           return false;
    510         }
    511       }
    512     }
    513     return true;
    514   }
    515 
    516   bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
    517     bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
    518     if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
    519       // We need to guard some of the invocation interface's calls: a bad caller might
    520       // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
    521       Thread* self = Thread::Current();
    522       if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
    523         ScopedObjectAccess soa(self);
    524         ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
    525         should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
    526       }
    527     }
    528     if (should_trace) {
    529       std::string msg;
    530       for (size_t i = 0; fmt[i] != '\0'; ++i) {
    531         TraceNonHeapValue(fmt[i], args[i], &msg);
    532         if (fmt[i + 1] != '\0') {
    533           StringAppendF(&msg, ", ");
    534         }
    535       }
    536 
    537       if ((flags_ & kFlag_ForceTrace) != 0) {
    538         LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
    539       } else if (entry) {
    540         if (has_method_) {
    541           Thread* self = Thread::Current();
    542           ScopedObjectAccess soa(self);
    543           ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
    544           std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
    545           LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
    546           indent_ = methodName.size() + 1;
    547         } else {
    548           LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
    549           indent_ = 0;
    550         }
    551       } else {
    552         LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
    553       }
    554     }
    555 
    556     // We always do the thorough checks on entry, and never on exit...
    557     if (entry) {
    558       for (size_t i = 0; fmt[i] != '\0'; ++i) {
    559         if (!CheckNonHeapValue(fmt[i], args[i])) {
    560           return false;
    561         }
    562       }
    563     }
    564     return true;
    565   }
    566 
    567   bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
    568       REQUIRES_SHARED(Locks::mutator_lock_) {
    569     ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
    570     if (method == nullptr) {
    571       AbortF("expected non-null method");
    572       return false;
    573     }
    574     mirror::Class* c = method->GetClass();
    575     if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
    576         soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
    577       AbortF("expected java.lang.reflect.Method or "
    578           "java.lang.reflect.Constructor but got object of type %s: %p",
    579           method->PrettyTypeOf().c_str(), jmethod);
    580       return false;
    581     }
    582     return true;
    583   }
    584 
    585   bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
    586     ArtMethod* method = jni::DecodeArtMethod(mid);
    587     if (method == nullptr) {
    588       AbortF("expected non-null constructor");
    589       return false;
    590     }
    591     if (!method->IsConstructor() || method->IsStatic()) {
    592       AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
    593       return false;
    594     }
    595     return true;
    596   }
    597 
    598   bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
    599       REQUIRES_SHARED(Locks::mutator_lock_) {
    600     ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
    601     if (field == nullptr) {
    602       AbortF("expected non-null java.lang.reflect.Field");
    603       return false;
    604     }
    605     mirror::Class* c = field->GetClass();
    606     if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
    607       AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
    608              field->PrettyTypeOf().c_str(), jfield);
    609       return false;
    610     }
    611     return true;
    612   }
    613 
    614   bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
    615       REQUIRES_SHARED(Locks::mutator_lock_) {
    616     ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
    617     if (!obj->GetClass()->IsThrowableClass()) {
    618       AbortF("expected java.lang.Throwable but got object of type "
    619              "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
    620       return false;
    621     }
    622     return true;
    623   }
    624 
    625   bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
    626       REQUIRES_SHARED(Locks::mutator_lock_) {
    627     ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
    628     if (!c->IsThrowableClass()) {
    629       AbortF("expected java.lang.Throwable class but got object of "
    630              "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
    631       return false;
    632     }
    633     return true;
    634   }
    635 
    636   bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
    637     IndirectRefKind found_kind;
    638     if (expected_kind == kLocal) {
    639       found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
    640       if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
    641         found_kind = kLocal;
    642       }
    643     } else {
    644       found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
    645     }
    646     if (obj != nullptr && found_kind != expected_kind) {
    647       AbortF("expected reference of kind %s but found %s: %p",
    648              GetIndirectRefKindString(expected_kind),
    649              GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
    650              obj);
    651       return false;
    652     }
    653     return true;
    654   }
    655 
    656   bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
    657       REQUIRES_SHARED(Locks::mutator_lock_) {
    658     ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
    659     if (!c->IsInstantiableNonArray()) {
    660       AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
    661       return false;
    662     }
    663     return true;
    664   }
    665 
    666   bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
    667       REQUIRES_SHARED(Locks::mutator_lock_) {
    668     if (!CheckArray(soa, array)) {
    669       return false;
    670     }
    671     ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
    672     if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
    673       AbortF("incompatible array type %s expected %s[]: %p",
    674              a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
    675       return false;
    676     }
    677     return true;
    678   }
    679 
    680   bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
    681                         Primitive::Type type)
    682       REQUIRES_SHARED(Locks::mutator_lock_) {
    683     if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
    684       return false;
    685     }
    686     if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
    687       return false;
    688     }
    689     ArtField* field = jni::DecodeArtField(fid);
    690     DCHECK(field != nullptr);  // Already checked by Check.
    691     if (is_static != field->IsStatic()) {
    692       AbortF("attempt to access %s field %s: %p",
    693              field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
    694       return false;
    695     }
    696     if (type != field->GetTypeAsPrimitiveType()) {
    697       AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
    698              field->PrettyField().c_str(),
    699              PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
    700              PrettyDescriptor(type).c_str(), fid);
    701       return false;
    702     }
    703     if (is_static) {
    704       ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
    705       if (o == nullptr || !o->IsClass()) {
    706         AbortF("attempt to access static field %s with a class argument of type %s: %p",
    707                field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
    708         return false;
    709       }
    710       ObjPtr<mirror::Class> c = o->AsClass();
    711       if (c != field->GetDeclaringClass()) {
    712         AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
    713                field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
    714         return false;
    715       }
    716     } else {
    717       ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
    718       if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
    719         AbortF("attempt to access field %s from an object argument of type %s: %p",
    720                field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
    721         return false;
    722       }
    723     }
    724     return true;
    725   }
    726 
    727  private:
    728   enum InstanceKind {
    729     kClass,
    730     kDirectByteBuffer,
    731     kObject,
    732     kString,
    733     kThrowable,
    734   };
    735 
    736   /*
    737    * Verify that "jobj" is a valid non-null object reference, and points to
    738    * an instance of expectedClass.
    739    *
    740    * Because we're looking at an object on the GC heap, we have to switch
    741    * to "running" mode before doing the checks.
    742    */
    743   bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
    744       REQUIRES_SHARED(Locks::mutator_lock_) {
    745     const char* what = nullptr;
    746     switch (kind) {
    747     case kClass:
    748       what = "jclass";
    749       break;
    750     case kDirectByteBuffer:
    751       what = "direct ByteBuffer";
    752       break;
    753     case kObject:
    754       what = "jobject";
    755       break;
    756     case kString:
    757       what = "jstring";
    758       break;
    759     case kThrowable:
    760       what = "jthrowable";
    761       break;
    762     default:
    763       LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
    764     }
    765 
    766     if (java_object == nullptr) {
    767       if (null_ok) {
    768         return true;
    769       } else {
    770         AbortF("%s received NULL %s", function_name_, what);
    771         return false;
    772       }
    773     }
    774 
    775     ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
    776     if (obj == nullptr) {
    777       // Either java_object is invalid or is a cleared weak.
    778       IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
    779       bool okay;
    780       if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
    781         okay = false;
    782       } else {
    783         obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
    784         okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
    785       }
    786       if (!okay) {
    787         AbortF("%s is an invalid %s: %p (%p)",
    788                what,
    789                GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
    790                java_object,
    791                obj.Ptr());
    792         return false;
    793       }
    794     }
    795 
    796     if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
    797       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
    798       AbortF("%s is an invalid %s: %p (%p)",
    799              what,
    800              GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
    801              java_object,
    802              obj.Ptr());
    803       return false;
    804     }
    805 
    806     bool okay = true;
    807     switch (kind) {
    808     case kClass:
    809       okay = obj->IsClass();
    810       break;
    811     case kDirectByteBuffer:
    812       UNIMPLEMENTED(FATAL);
    813       break;
    814     case kString:
    815       okay = obj->GetClass()->IsStringClass();
    816       break;
    817     case kThrowable:
    818       okay = obj->GetClass()->IsThrowableClass();
    819       break;
    820     case kObject:
    821       break;
    822     }
    823     if (!okay) {
    824       AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
    825       return false;
    826     }
    827 
    828     return true;
    829   }
    830 
    831   /*
    832    * Verify that the "mode" argument passed to a primitive array Release
    833    * function is one of the valid values.
    834    */
    835   bool CheckReleaseMode(jint mode) {
    836     if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
    837       AbortF("unknown value for release mode: %d", mode);
    838       return false;
    839     }
    840     return true;
    841   }
    842 
    843   bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
    844       REQUIRES_SHARED(Locks::mutator_lock_) {
    845     switch (fmt) {
    846       case 'a':  // jarray
    847         return CheckArray(soa, arg.a);
    848       case 'c':  // jclass
    849         return CheckInstance(soa, kClass, arg.c, false);
    850       case 'f':  // jfieldID
    851         return CheckFieldID(arg.f) != nullptr;
    852       case 'm':  // jmethodID
    853         return CheckMethodID(arg.m) != nullptr;
    854       case 'r':  // release int
    855         return CheckReleaseMode(arg.r);
    856       case 's':  // jstring
    857         return CheckInstance(soa, kString, arg.s, false);
    858       case 't':  // jthrowable
    859         return CheckInstance(soa, kThrowable, arg.t, false);
    860       case 'E':  // JNIEnv*
    861         return CheckThread(arg.E);
    862       case 'L':  // jobject
    863         return CheckInstance(soa, kObject, arg.L, true);
    864       case '.':  // A VarArgs list
    865         return CheckVarArgs(soa, arg.va);
    866       default:
    867         return CheckNonHeapValue(fmt, arg);
    868     }
    869   }
    870 
    871   bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
    872       REQUIRES_SHARED(Locks::mutator_lock_) {
    873     CHECK(args_p != nullptr);
    874     VarArgs args(args_p->Clone());
    875     ArtMethod* m = CheckMethodID(args.GetMethodID());
    876     if (m == nullptr) {
    877       return false;
    878     }
    879     uint32_t len = 0;
    880     const char* shorty = m->GetShorty(&len);
    881     // Skip the return type
    882     CHECK_GE(len, 1u);
    883     len--;
    884     shorty++;
    885     for (uint32_t i = 0; i < len; i++) {
    886       if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
    887         return false;
    888       }
    889     }
    890     return true;
    891   }
    892 
    893   bool CheckNonHeapValue(char fmt, JniValueType arg) {
    894     switch (fmt) {
    895       case 'p':  // TODO: pointer - null or readable?
    896       case 'v':  // JavaVM*
    897       case 'B':  // jbyte
    898       case 'C':  // jchar
    899       case 'D':  // jdouble
    900       case 'F':  // jfloat
    901       case 'I':  // jint
    902       case 'J':  // jlong
    903       case 'S':  // jshort
    904         break;  // Ignored.
    905       case 'b':  // jboolean, why two? Fall-through.
    906       case 'Z':
    907         return CheckBoolean(arg.Z);
    908       case 'u':  // utf8
    909         if ((flags_ & kFlag_Release) != 0) {
    910           return CheckNonNull(arg.u);
    911         } else {
    912           bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
    913           return CheckUtfString(arg.u, nullable);
    914         }
    915       case 'w':  // jobjectRefType
    916         switch (arg.w) {
    917           case JNIInvalidRefType:
    918           case JNILocalRefType:
    919           case JNIGlobalRefType:
    920           case JNIWeakGlobalRefType:
    921             break;
    922           default:
    923             AbortF("Unknown reference type");
    924             return false;
    925         }
    926         break;
    927       case 'z':  // jsize
    928         return CheckLengthPositive(arg.z);
    929       default:
    930         AbortF("unknown format specifier: '%c'", fmt);
    931         return false;
    932     }
    933     return true;
    934   }
    935 
    936   void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
    937                               std::string* msg)
    938       REQUIRES_SHARED(Locks::mutator_lock_) {
    939     switch (fmt) {
    940       case 'L':  // jobject fall-through.
    941       case 'a':  // jarray fall-through.
    942       case 's':  // jstring fall-through.
    943       case 't':  // jthrowable fall-through.
    944         if (arg.L == nullptr) {
    945           *msg += "NULL";
    946         } else {
    947           StringAppendF(msg, "%p", arg.L);
    948         }
    949         break;
    950       case 'c': {  // jclass
    951         jclass jc = arg.c;
    952         ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
    953         if (c == nullptr) {
    954           *msg += "NULL";
    955         } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
    956           StringAppendF(msg, "INVALID POINTER:%p", jc);
    957         } else if (!c->IsClass()) {
    958           *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
    959         } else {
    960           *msg += c->PrettyClass();
    961           if (!entry) {
    962             StringAppendF(msg, " (%p)", jc);
    963           }
    964         }
    965         break;
    966       }
    967       case 'f': {  // jfieldID
    968         jfieldID fid = arg.f;
    969         ArtField* f = jni::DecodeArtField(fid);
    970         *msg += ArtField::PrettyField(f);
    971         if (!entry) {
    972           StringAppendF(msg, " (%p)", fid);
    973         }
    974         break;
    975       }
    976       case 'm': {  // jmethodID
    977         jmethodID mid = arg.m;
    978         ArtMethod* m = jni::DecodeArtMethod(mid);
    979         *msg += ArtMethod::PrettyMethod(m);
    980         if (!entry) {
    981           StringAppendF(msg, " (%p)", mid);
    982         }
    983         break;
    984       }
    985       case '.': {
    986         const VarArgs* va = arg.va;
    987         VarArgs args(va->Clone());
    988         ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
    989         uint32_t len;
    990         const char* shorty = m->GetShorty(&len);
    991         CHECK_GE(len, 1u);
    992         // Skip past return value.
    993         len--;
    994         shorty++;
    995         // Remove the previous ', ' from the message.
    996         msg->erase(msg->length() - 2);
    997         for (uint32_t i = 0; i < len; i++) {
    998           *msg += ", ";
    999           TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
   1000         }
   1001         break;
   1002       }
   1003       default:
   1004         TraceNonHeapValue(fmt, arg, msg);
   1005         break;
   1006     }
   1007   }
   1008 
   1009   void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
   1010     switch (fmt) {
   1011       case 'B':  // jbyte
   1012         if (arg.B >= 0 && arg.B < 10) {
   1013           StringAppendF(msg, "%d", arg.B);
   1014         } else {
   1015           StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
   1016         }
   1017         break;
   1018       case 'C':  // jchar
   1019         if (arg.C < 0x7f && arg.C >= ' ') {
   1020           StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
   1021         } else {
   1022           StringAppendF(msg, "U+%x", arg.C);
   1023         }
   1024         break;
   1025       case 'F':  // jfloat
   1026         StringAppendF(msg, "%g", arg.F);
   1027         break;
   1028       case 'D':  // jdouble
   1029         StringAppendF(msg, "%g", arg.D);
   1030         break;
   1031       case 'S':  // jshort
   1032         StringAppendF(msg, "%d", arg.S);
   1033         break;
   1034       case 'i':  // jint - fall-through.
   1035       case 'I':  // jint
   1036         StringAppendF(msg, "%d", arg.I);
   1037         break;
   1038       case 'J':  // jlong
   1039         StringAppendF(msg, "%" PRId64, arg.J);
   1040         break;
   1041       case 'Z':  // jboolean
   1042       case 'b':  // jboolean (JNI-style)
   1043         *msg += arg.b == JNI_TRUE ? "true" : "false";
   1044         break;
   1045       case 'V':  // void
   1046         DCHECK(arg.V == nullptr);
   1047         *msg += "void";
   1048         break;
   1049       case 'v':  // JavaVM*
   1050         StringAppendF(msg, "(JavaVM*)%p", arg.v);
   1051         break;
   1052       case 'E':
   1053         StringAppendF(msg, "(JNIEnv*)%p", arg.E);
   1054         break;
   1055       case 'z':  // non-negative jsize
   1056         // You might expect jsize to be size_t, but it's not; it's the same as jint.
   1057         // We only treat this specially so we can do the non-negative check.
   1058         // TODO: maybe this wasn't worth it?
   1059         StringAppendF(msg, "%d", arg.z);
   1060         break;
   1061       case 'p':  // void* ("pointer")
   1062         if (arg.p == nullptr) {
   1063           *msg += "NULL";
   1064         } else {
   1065           StringAppendF(msg, "(void*) %p", arg.p);
   1066         }
   1067         break;
   1068       case 'r': {  // jint (release mode)
   1069         jint releaseMode = arg.r;
   1070         if (releaseMode == 0) {
   1071           *msg += "0";
   1072         } else if (releaseMode == JNI_ABORT) {
   1073           *msg += "JNI_ABORT";
   1074         } else if (releaseMode == JNI_COMMIT) {
   1075           *msg += "JNI_COMMIT";
   1076         } else {
   1077           StringAppendF(msg, "invalid release mode %d", releaseMode);
   1078         }
   1079         break;
   1080       }
   1081       case 'u':  // const char* (Modified UTF-8)
   1082         if (arg.u == nullptr) {
   1083           *msg += "NULL";
   1084         } else {
   1085           StringAppendF(msg, "\"%s\"", arg.u);
   1086         }
   1087         break;
   1088       case 'w':  // jobjectRefType
   1089         switch (arg.w) {
   1090           case JNIInvalidRefType:
   1091             *msg += "invalid reference type";
   1092             break;
   1093           case JNILocalRefType:
   1094             *msg += "local ref type";
   1095             break;
   1096           case JNIGlobalRefType:
   1097             *msg += "global ref type";
   1098             break;
   1099           case JNIWeakGlobalRefType:
   1100             *msg += "weak global ref type";
   1101             break;
   1102           default:
   1103             *msg += "unknown ref type";
   1104             break;
   1105         }
   1106         break;
   1107       default:
   1108         LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
   1109     }
   1110   }
   1111   /*
   1112    * Verify that "array" is non-null and points to an Array object.
   1113    *
   1114    * Since we're dealing with objects, switch to "running" mode.
   1115    */
   1116   bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
   1117       REQUIRES_SHARED(Locks::mutator_lock_) {
   1118     if (UNLIKELY(java_array == nullptr)) {
   1119       AbortF("jarray was NULL");
   1120       return false;
   1121     }
   1122 
   1123     ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
   1124     if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
   1125       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
   1126       AbortF("jarray is an invalid %s: %p (%p)",
   1127              GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
   1128              java_array,
   1129              a.Ptr());
   1130       return false;
   1131     } else if (!a->IsArrayInstance()) {
   1132       AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
   1133       return false;
   1134     }
   1135     return true;
   1136   }
   1137 
   1138   bool CheckBoolean(jboolean z) {
   1139     if (z != JNI_TRUE && z != JNI_FALSE) {
   1140       AbortF("unexpected jboolean value: %d", z);
   1141       return false;
   1142     }
   1143     return true;
   1144   }
   1145 
   1146   bool CheckLengthPositive(jsize length) {
   1147     if (length < 0) {
   1148       AbortF("negative jsize: %d", length);
   1149       return false;
   1150     }
   1151     return true;
   1152   }
   1153 
   1154   ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
   1155     if (fid == nullptr) {
   1156       AbortF("jfieldID was NULL");
   1157       return nullptr;
   1158     }
   1159     ArtField* f = jni::DecodeArtField(fid);
   1160     // TODO: Better check here.
   1161     if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
   1162       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
   1163       AbortF("invalid jfieldID: %p", fid);
   1164       return nullptr;
   1165     }
   1166     return f;
   1167   }
   1168 
   1169   ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
   1170     if (mid == nullptr) {
   1171       AbortF("jmethodID was NULL");
   1172       return nullptr;
   1173     }
   1174     ArtMethod* m = jni::DecodeArtMethod(mid);
   1175     // TODO: Better check here.
   1176     if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
   1177       Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
   1178       AbortF("invalid jmethodID: %p", mid);
   1179       return nullptr;
   1180     }
   1181     return m;
   1182   }
   1183 
   1184   bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
   1185     Thread* self = Thread::Current();
   1186     if (self == nullptr) {
   1187       AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
   1188       return false;
   1189     }
   1190 
   1191     // Get the current thread's JNIEnv by going through our TLS pointer.
   1192     JNIEnvExt* threadEnv = self->GetJniEnv();
   1193 
   1194     // Verify that the current thread is (a) attached and (b) associated with
   1195     // this particular instance of JNIEnv.
   1196     if (env != threadEnv) {
   1197       // Get the thread owning the JNIEnv that's being used.
   1198       Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self;
   1199       AbortF("thread %s using JNIEnv* from thread %s",
   1200              ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
   1201       return false;
   1202     }
   1203 
   1204     // Verify that, if this thread previously made a critical "get" call, we
   1205     // do the corresponding "release" call before we try anything else.
   1206     switch (flags_ & kFlag_CritMask) {
   1207     case kFlag_CritOkay:    // okay to call this method
   1208       break;
   1209     case kFlag_CritBad:     // not okay to call
   1210       if (threadEnv->critical) {
   1211         AbortF("thread %s using JNI after critical get",
   1212                ToStr<Thread>(*self).c_str());
   1213         return false;
   1214       }
   1215       break;
   1216     case kFlag_CritGet:     // this is a "get" call
   1217       // Don't check here; we allow nested gets.
   1218       threadEnv->critical++;
   1219       break;
   1220     case kFlag_CritRelease:  // this is a "release" call
   1221       threadEnv->critical--;
   1222       if (threadEnv->critical < 0) {
   1223         AbortF("thread %s called too many critical releases",
   1224                ToStr<Thread>(*self).c_str());
   1225         return false;
   1226       }
   1227       break;
   1228     default:
   1229       LOG(FATAL) << "Bad flags (internal error): " << flags_;
   1230     }
   1231 
   1232     // Verify that, if an exception has been raised, the native code doesn't
   1233     // make any JNI calls other than the Exception* methods.
   1234     if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
   1235       mirror::Throwable* exception = self->GetException();
   1236       AbortF("JNI %s called with pending exception %s",
   1237              function_name_,
   1238              exception->Dump().c_str());
   1239       return false;
   1240     }
   1241     return true;
   1242   }
   1243 
   1244   // Verifies that "bytes" points to valid Modified UTF-8 data.
   1245   bool CheckUtfString(const char* bytes, bool nullable) {
   1246     if (bytes == nullptr) {
   1247       if (!nullable) {
   1248         AbortF("non-nullable const char* was NULL");
   1249         return false;
   1250       }
   1251       return true;
   1252     }
   1253 
   1254     const char* errorKind = nullptr;
   1255     const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
   1256     if (errorKind != nullptr) {
   1257       // This is an expensive loop that will resize often, but this isn't supposed to hit in
   1258       // practice anyways.
   1259       std::ostringstream oss;
   1260       oss << std::hex;
   1261       const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
   1262       while (*tmp != 0) {
   1263         if (tmp == utf8) {
   1264           oss << "<";
   1265         }
   1266         oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
   1267         if (tmp == utf8) {
   1268           oss << '>';
   1269         }
   1270         tmp++;
   1271         if (*tmp != 0) {
   1272           oss << ' ';
   1273         }
   1274       }
   1275 
   1276       AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
   1277           "    string: '%s'\n    input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
   1278       return false;
   1279     }
   1280     return true;
   1281   }
   1282 
   1283   // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
   1284   // sequences in place of encoded surrogate pairs.
   1285   static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
   1286     while (*bytes != '\0') {
   1287       const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
   1288       // Switch on the high four bits.
   1289       switch (*utf8 >> 4) {
   1290       case 0x00:
   1291       case 0x01:
   1292       case 0x02:
   1293       case 0x03:
   1294       case 0x04:
   1295       case 0x05:
   1296       case 0x06:
   1297       case 0x07:
   1298         // Bit pattern 0xxx. No need for any extra bytes.
   1299         break;
   1300       case 0x08:
   1301       case 0x09:
   1302       case 0x0a:
   1303       case 0x0b:
   1304          // Bit patterns 10xx, which are illegal start bytes.
   1305         *errorKind = "start";
   1306         return utf8;
   1307       case 0x0f:
   1308         // Bit pattern 1111, which might be the start of a 4 byte sequence.
   1309         if ((*utf8 & 0x08) == 0) {
   1310           // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
   1311           // We consume one continuation byte here, and fall through to consume two more.
   1312           utf8 = reinterpret_cast<const uint8_t*>(bytes++);
   1313           if ((*utf8 & 0xc0) != 0x80) {
   1314             *errorKind = "continuation";
   1315             return utf8;
   1316           }
   1317         } else {
   1318           *errorKind = "start";
   1319           return utf8;
   1320         }
   1321 
   1322         // Fall through to the cases below to consume two more continuation bytes.
   1323         FALLTHROUGH_INTENDED;
   1324       case 0x0e:
   1325         // Bit pattern 1110, so there are two additional bytes.
   1326         utf8 = reinterpret_cast<const uint8_t*>(bytes++);
   1327         if ((*utf8 & 0xc0) != 0x80) {
   1328           *errorKind = "continuation";
   1329           return utf8;
   1330         }
   1331 
   1332         // Fall through to consume one more continuation byte.
   1333         FALLTHROUGH_INTENDED;
   1334       case 0x0c:
   1335       case 0x0d:
   1336         // Bit pattern 110x, so there is one additional byte.
   1337         utf8 = reinterpret_cast<const uint8_t*>(bytes++);
   1338         if ((*utf8 & 0xc0) != 0x80) {
   1339           *errorKind = "continuation";
   1340           return utf8;
   1341         }
   1342         break;
   1343       }
   1344     }
   1345     return 0;
   1346   }
   1347 
   1348   void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
   1349     va_list args;
   1350     va_start(args, fmt);
   1351     Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
   1352     va_end(args);
   1353   }
   1354 
   1355   // The name of the JNI function being checked.
   1356   const char* const function_name_;
   1357 
   1358   const int flags_;
   1359   int indent_;
   1360 
   1361   const bool has_method_;
   1362 
   1363   DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
   1364 };
   1365 
   1366 /*
   1367  * ===========================================================================
   1368  *      Guarded arrays
   1369  * ===========================================================================
   1370  */
   1371 
   1372 /* this gets tucked in at the start of the buffer; struct size must be even */
   1373 class GuardedCopy {
   1374  public:
   1375   /*
   1376    * Create an over-sized buffer to hold the contents of "buf".  Copy it in,
   1377    * filling in the area around it with guard data.
   1378    */
   1379   static void* Create(void* original_buf, size_t len, bool mod_okay) {
   1380     const size_t new_len = LengthIncludingRedZones(len);
   1381     uint8_t* const new_buf = DebugAlloc(new_len);
   1382 
   1383     // If modification is not expected, grab a checksum.
   1384     uLong adler = 0;
   1385     if (!mod_okay) {
   1386       adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
   1387     }
   1388 
   1389     GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
   1390 
   1391     // Fill begin region with canary pattern.
   1392     const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
   1393     for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
   1394       const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
   1395       if (kCanary[j] == '\0') {
   1396         j = 0;
   1397       } else {
   1398         j++;
   1399       }
   1400     }
   1401 
   1402     // Copy the data in; note "len" could be zero.
   1403     memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
   1404 
   1405     // Fill end region with canary pattern.
   1406     for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
   1407       const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
   1408       if (kCanary[j] == '\0') {
   1409         j = 0;
   1410       } else {
   1411         j++;
   1412       }
   1413     }
   1414 
   1415     return const_cast<uint8_t*>(copy->BufferWithinRedZones());
   1416   }
   1417 
   1418   /*
   1419    * Create a guarded copy of a primitive array.  Modifications to the copied
   1420    * data are allowed.  Returns a pointer to the copied data.
   1421    */
   1422   static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
   1423                                    void* original_ptr) {
   1424     ScopedObjectAccess soa(env);
   1425 
   1426     ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
   1427     size_t component_size = a->GetClass()->GetComponentSize();
   1428     size_t byte_count = a->GetLength() * component_size;
   1429     void* result = Create(original_ptr, byte_count, true);
   1430     if (is_copy != nullptr) {
   1431       *is_copy = JNI_TRUE;
   1432     }
   1433     return result;
   1434   }
   1435 
   1436   /*
   1437    * Perform the array "release" operation, which may or may not copy data
   1438    * back into the managed heap, and may or may not release the underlying storage.
   1439    */
   1440   static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
   1441                                     jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
   1442                                     int mode) {
   1443     ScopedObjectAccess soa(env);
   1444     if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
   1445       return nullptr;
   1446     }
   1447     GuardedCopy* const copy = FromEmbedded(embedded_buf);
   1448     void* original_ptr = copy->original_ptr_;
   1449     if (mode != JNI_ABORT) {
   1450       memcpy(original_ptr, embedded_buf, copy->original_length_);
   1451     }
   1452     if (mode != JNI_COMMIT) {
   1453       Destroy(embedded_buf);
   1454     }
   1455     return original_ptr;
   1456   }
   1457 
   1458 
   1459   /*
   1460    * Free up the guard buffer, scrub it, and return the original pointer.
   1461    */
   1462   static void* Destroy(void* embedded_buf) {
   1463     GuardedCopy* copy = FromEmbedded(embedded_buf);
   1464     void* original_ptr = const_cast<void*>(copy->original_ptr_);
   1465     size_t len = LengthIncludingRedZones(copy->original_length_);
   1466     DebugFree(copy, len);
   1467     return original_ptr;
   1468   }
   1469 
   1470   /*
   1471    * Verify the guard area and, if "modOkay" is false, that the data itself
   1472    * has not been altered.
   1473    *
   1474    * The caller has already checked that "dataBuf" is non-null.
   1475    */
   1476   static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
   1477     const GuardedCopy* copy = FromEmbedded(embedded_buf);
   1478     return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
   1479   }
   1480 
   1481  private:
   1482   GuardedCopy(void* original_buf, size_t len, uLong adler) :
   1483     magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
   1484   }
   1485 
   1486   static uint8_t* DebugAlloc(size_t len) {
   1487     void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
   1488     if (result == MAP_FAILED) {
   1489       PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
   1490     }
   1491     return reinterpret_cast<uint8_t*>(result);
   1492   }
   1493 
   1494   static void DebugFree(void* buf, size_t len) {
   1495     if (munmap(buf, len) != 0) {
   1496       PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
   1497     }
   1498   }
   1499 
   1500   static size_t LengthIncludingRedZones(size_t len) {
   1501     return len + kRedZoneSize;
   1502   }
   1503 
   1504   // Get the GuardedCopy from the interior pointer.
   1505   static GuardedCopy* FromEmbedded(void* embedded_buf) {
   1506     return reinterpret_cast<GuardedCopy*>(
   1507         reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
   1508   }
   1509 
   1510   static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
   1511     return reinterpret_cast<const GuardedCopy*>(
   1512         reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
   1513   }
   1514 
   1515   static void AbortF(const char* jni_function_name, const char* fmt, ...) {
   1516     va_list args;
   1517     va_start(args, fmt);
   1518     Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
   1519     va_end(args);
   1520   }
   1521 
   1522   bool CheckHeader(const char* function_name, bool mod_okay) const {
   1523     static const uint32_t kMagicCmp = kGuardMagic;
   1524 
   1525     // Before we do anything with "pExtra", check the magic number.  We
   1526     // do the check with memcmp rather than "==" in case the pointer is
   1527     // unaligned.  If it points to completely bogus memory we're going
   1528     // to crash, but there's no easy way around that.
   1529     if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
   1530       uint8_t buf[4];
   1531       memcpy(buf, &magic_, 4);
   1532       AbortF(function_name,
   1533              "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
   1534              buf[3], buf[2], buf[1], buf[0], this);  // Assumes little-endian.
   1535       return false;
   1536     }
   1537 
   1538     // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
   1539     // told the client that we made a copy, there's no reason they can't alter the buffer.
   1540     if (!mod_okay) {
   1541       uLong computed_adler =
   1542           adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
   1543       if (computed_adler != adler_) {
   1544         AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
   1545                computed_adler, adler_, this);
   1546         return false;
   1547       }
   1548     }
   1549     return true;
   1550   }
   1551 
   1552   bool CheckRedZones(const char* function_name) const {
   1553     // Check the begin red zone.
   1554     const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
   1555     for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
   1556       if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
   1557         AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
   1558         return false;
   1559       }
   1560       if (kCanary[j] == '\0') {
   1561         j = 0;
   1562       } else {
   1563         j++;
   1564       }
   1565     }
   1566 
   1567     // Check end region.
   1568     for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
   1569       if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
   1570         size_t offset_from_buffer_start =
   1571             &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
   1572         AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
   1573                offset_from_buffer_start);
   1574         return false;
   1575       }
   1576       if (kCanary[j] == '\0') {
   1577         j = 0;
   1578       } else {
   1579         j++;
   1580       }
   1581     }
   1582     return true;
   1583   }
   1584 
   1585   // Location that canary value will be written before the guarded region.
   1586   const char* StartRedZone() const {
   1587     const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
   1588     return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
   1589   }
   1590 
   1591   // Return the interior embedded buffer.
   1592   const uint8_t* BufferWithinRedZones() const {
   1593     const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
   1594     return embedded_buf;
   1595   }
   1596 
   1597   // Location that canary value will be written after the guarded region.
   1598   const char* EndRedZone() const {
   1599     const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
   1600     size_t buf_len = LengthIncludingRedZones(original_length_);
   1601     return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
   1602   }
   1603 
   1604   static constexpr size_t kRedZoneSize = 512;
   1605   static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
   1606 
   1607   // Value written before and after the guarded array.
   1608   static const char* const kCanary;
   1609 
   1610   static constexpr uint32_t kGuardMagic = 0xffd5aa96;
   1611 
   1612   const uint32_t magic_;
   1613   const uLong adler_;
   1614   void* const original_ptr_;
   1615   const size_t original_length_;
   1616 };
   1617 const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
   1618 
   1619 /*
   1620  * ===========================================================================
   1621  *      JNI functions
   1622  * ===========================================================================
   1623  */
   1624 
   1625 class CheckJNI {
   1626  public:
   1627   static jint GetVersion(JNIEnv* env) {
   1628     ScopedObjectAccess soa(env);
   1629     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1630     JniValueType args[1] = {{.E = env }};
   1631     if (sc.Check(soa, true, "E", args)) {
   1632       JniValueType result;
   1633       result.I = baseEnv(env)->GetVersion(env);
   1634       if (sc.Check(soa, false, "I", &result)) {
   1635         return result.I;
   1636       }
   1637     }
   1638     return JNI_ERR;
   1639   }
   1640 
   1641   static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
   1642     ScopedObjectAccess soa(env);
   1643     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1644     JniValueType args[2] = {{.E = env }, {.p = vm}};
   1645     if (sc.Check(soa, true, "Ep", args)) {
   1646       JniValueType result;
   1647       result.i = baseEnv(env)->GetJavaVM(env, vm);
   1648       if (sc.Check(soa, false, "i", &result)) {
   1649         return result.i;
   1650       }
   1651     }
   1652     return JNI_ERR;
   1653   }
   1654 
   1655   static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
   1656     ScopedObjectAccess soa(env);
   1657     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1658     JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
   1659     if (sc.Check(soa, true, "EcpI", args)) {
   1660       JniValueType result;
   1661       result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
   1662       if (sc.Check(soa, false, "i", &result)) {
   1663         return result.i;
   1664       }
   1665     }
   1666     return JNI_ERR;
   1667   }
   1668 
   1669   static jint UnregisterNatives(JNIEnv* env, jclass c) {
   1670     ScopedObjectAccess soa(env);
   1671     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1672     JniValueType args[2] = {{.E = env }, {.c = c}};
   1673     if (sc.Check(soa, true, "Ec", args)) {
   1674       JniValueType result;
   1675       result.i = baseEnv(env)->UnregisterNatives(env, c);
   1676       if (sc.Check(soa, false, "i", &result)) {
   1677         return result.i;
   1678       }
   1679     }
   1680     return JNI_ERR;
   1681   }
   1682 
   1683   static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
   1684     // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
   1685     // know the object is invalid. The spec says that passing invalid objects or even ones that
   1686     // are deleted isn't supported.
   1687     ScopedObjectAccess soa(env);
   1688     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1689     JniValueType args[2] = {{.E = env }, {.L = obj}};
   1690     if (sc.Check(soa, true, "EL", args)) {
   1691       JniValueType result;
   1692       result.w = baseEnv(env)->GetObjectRefType(env, obj);
   1693       if (sc.Check(soa, false, "w", &result)) {
   1694         return result.w;
   1695       }
   1696     }
   1697     return JNIInvalidRefType;
   1698   }
   1699 
   1700   static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
   1701                             jsize bufLen) {
   1702     ScopedObjectAccess soa(env);
   1703     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1704     JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
   1705     if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
   1706       JniValueType result;
   1707       result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
   1708       if (sc.Check(soa, false, "c", &result)) {
   1709         return result.c;
   1710       }
   1711     }
   1712     return nullptr;
   1713   }
   1714 
   1715   static jclass FindClass(JNIEnv* env, const char* name) {
   1716     ScopedObjectAccess soa(env);
   1717     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1718     JniValueType args[2] = {{.E = env}, {.u = name}};
   1719     if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
   1720       JniValueType result;
   1721       result.c = baseEnv(env)->FindClass(env, name);
   1722       if (sc.Check(soa, false, "c", &result)) {
   1723         return result.c;
   1724       }
   1725     }
   1726     return nullptr;
   1727   }
   1728 
   1729   static jclass GetSuperclass(JNIEnv* env, jclass c) {
   1730     ScopedObjectAccess soa(env);
   1731     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1732     JniValueType args[2] = {{.E = env}, {.c = c}};
   1733     if (sc.Check(soa, true, "Ec", args)) {
   1734       JniValueType result;
   1735       result.c = baseEnv(env)->GetSuperclass(env, c);
   1736       if (sc.Check(soa, false, "c", &result)) {
   1737         return result.c;
   1738       }
   1739     }
   1740     return nullptr;
   1741   }
   1742 
   1743   static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
   1744     ScopedObjectAccess soa(env);
   1745     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1746     JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
   1747     if (sc.Check(soa, true, "Ecc", args)) {
   1748       JniValueType result;
   1749       result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
   1750       if (sc.Check(soa, false, "b", &result)) {
   1751         return result.b;
   1752       }
   1753     }
   1754     return JNI_FALSE;
   1755   }
   1756 
   1757   static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
   1758     ScopedObjectAccess soa(env);
   1759     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1760     JniValueType args[2] = {{.E = env}, {.L = method}};
   1761     if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
   1762       JniValueType result;
   1763       result.m = baseEnv(env)->FromReflectedMethod(env, method);
   1764       if (sc.Check(soa, false, "m", &result)) {
   1765         return result.m;
   1766       }
   1767     }
   1768     return nullptr;
   1769   }
   1770 
   1771   static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
   1772     ScopedObjectAccess soa(env);
   1773     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1774     JniValueType args[2] = {{.E = env}, {.L = field}};
   1775     if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
   1776       JniValueType result;
   1777       result.f = baseEnv(env)->FromReflectedField(env, field);
   1778       if (sc.Check(soa, false, "f", &result)) {
   1779         return result.f;
   1780       }
   1781     }
   1782     return nullptr;
   1783   }
   1784 
   1785   static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
   1786     ScopedObjectAccess soa(env);
   1787     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1788     JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
   1789     if (sc.Check(soa, true, "Ecmb", args)) {
   1790       JniValueType result;
   1791       result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
   1792       if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
   1793         DCHECK(sc.CheckReflectedMethod(soa, result.L));
   1794         return result.L;
   1795       }
   1796     }
   1797     return nullptr;
   1798   }
   1799 
   1800   static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
   1801     ScopedObjectAccess soa(env);
   1802     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1803     JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
   1804     if (sc.Check(soa, true, "Ecfb", args)) {
   1805       JniValueType result;
   1806       result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
   1807       if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
   1808         DCHECK(sc.CheckReflectedField(soa, result.L));
   1809         return result.L;
   1810       }
   1811     }
   1812     return nullptr;
   1813   }
   1814 
   1815   static jint Throw(JNIEnv* env, jthrowable obj) {
   1816     ScopedObjectAccess soa(env);
   1817     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1818     JniValueType args[2] = {{.E = env}, {.t = obj}};
   1819     if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
   1820       JniValueType result;
   1821       result.i = baseEnv(env)->Throw(env, obj);
   1822       if (sc.Check(soa, false, "i", &result)) {
   1823         return result.i;
   1824       }
   1825     }
   1826     return JNI_ERR;
   1827   }
   1828 
   1829   static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
   1830     ScopedObjectAccess soa(env);
   1831     ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
   1832     JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
   1833     if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
   1834       JniValueType result;
   1835       result.i = baseEnv(env)->ThrowNew(env, c, message);
   1836       if (sc.Check(soa, false, "i", &result)) {
   1837         return result.i;
   1838       }
   1839     }
   1840     return JNI_ERR;
   1841   }
   1842 
   1843   static jthrowable ExceptionOccurred(JNIEnv* env) {
   1844     ScopedObjectAccess soa(env);
   1845     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
   1846     JniValueType args[1] = {{.E = env}};
   1847     if (sc.Check(soa, true, "E", args)) {
   1848       JniValueType result;
   1849       result.t = baseEnv(env)->ExceptionOccurred(env);
   1850       if (sc.Check(soa, false, "t", &result)) {
   1851         return result.t;
   1852       }
   1853     }
   1854     return nullptr;
   1855   }
   1856 
   1857   static void ExceptionDescribe(JNIEnv* env) {
   1858     ScopedObjectAccess soa(env);
   1859     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
   1860     JniValueType args[1] = {{.E = env}};
   1861     if (sc.Check(soa, true, "E", args)) {
   1862       JniValueType result;
   1863       baseEnv(env)->ExceptionDescribe(env);
   1864       result.V = nullptr;
   1865       sc.Check(soa, false, "V", &result);
   1866     }
   1867   }
   1868 
   1869   static void ExceptionClear(JNIEnv* env) {
   1870     ScopedObjectAccess soa(env);
   1871     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
   1872     JniValueType args[1] = {{.E = env}};
   1873     if (sc.Check(soa, true, "E", args)) {
   1874       JniValueType result;
   1875       baseEnv(env)->ExceptionClear(env);
   1876       result.V = nullptr;
   1877       sc.Check(soa, false, "V", &result);
   1878     }
   1879   }
   1880 
   1881   static jboolean ExceptionCheck(JNIEnv* env) {
   1882     ScopedObjectAccess soa(env);
   1883     ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
   1884     JniValueType args[1] = {{.E = env}};
   1885     if (sc.Check(soa, true, "E", args)) {
   1886       JniValueType result;
   1887       result.b = baseEnv(env)->ExceptionCheck(env);
   1888       if (sc.Check(soa, false, "b", &result)) {
   1889         return result.b;
   1890       }
   1891     }
   1892     return JNI_FALSE;
   1893   }
   1894 
   1895   static void FatalError(JNIEnv* env, const char* msg) {
   1896     // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
   1897     // but you're about to abort anyway, and it's quite likely that you have a pending exception,
   1898     // and it's not unimaginable that you don't know that you do. So we allow it.
   1899     ScopedObjectAccess soa(env);
   1900     ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
   1901     JniValueType args[2] = {{.E = env}, {.u = msg}};
   1902     if (sc.Check(soa, true, "Eu", args)) {
   1903       JniValueType result;
   1904       baseEnv(env)->FatalError(env, msg);
   1905       // Unreachable.
   1906       result.V = nullptr;
   1907       sc.Check(soa, false, "V", &result);
   1908     }
   1909   }
   1910 
   1911   static jint PushLocalFrame(JNIEnv* env, jint capacity) {
   1912     ScopedObjectAccess soa(env);
   1913     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
   1914     JniValueType args[2] = {{.E = env}, {.I = capacity}};
   1915     if (sc.Check(soa, true, "EI", args)) {
   1916       JniValueType result;
   1917       result.i = baseEnv(env)->PushLocalFrame(env, capacity);
   1918       if (sc.Check(soa, false, "i", &result)) {
   1919         return result.i;
   1920       }
   1921     }
   1922     return JNI_ERR;
   1923   }
   1924 
   1925   static jobject PopLocalFrame(JNIEnv* env, jobject res) {
   1926     ScopedObjectAccess soa(env);
   1927     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
   1928     JniValueType args[2] = {{.E = env}, {.L = res}};
   1929     if (sc.Check(soa, true, "EL", args)) {
   1930       JniValueType result;
   1931       result.L = baseEnv(env)->PopLocalFrame(env, res);
   1932       sc.Check(soa, false, "L", &result);
   1933       return result.L;
   1934     }
   1935     return nullptr;
   1936   }
   1937 
   1938   static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
   1939     return NewRef(__FUNCTION__, env, obj, kGlobal);
   1940   }
   1941 
   1942   static jobject NewLocalRef(JNIEnv* env, jobject obj) {
   1943     return NewRef(__FUNCTION__, env, obj, kLocal);
   1944   }
   1945 
   1946   static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
   1947     return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
   1948   }
   1949 
   1950   static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
   1951     DeleteRef(__FUNCTION__, env, obj, kGlobal);
   1952   }
   1953 
   1954   static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
   1955     DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
   1956   }
   1957 
   1958   static void DeleteLocalRef(JNIEnv* env, jobject obj) {
   1959     DeleteRef(__FUNCTION__, env, obj, kLocal);
   1960   }
   1961 
   1962   static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
   1963     ScopedObjectAccess soa(env);
   1964     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1965     JniValueType args[2] = {{.E = env}, {.I = capacity}};
   1966     if (sc.Check(soa, true, "EI", args)) {
   1967       JniValueType result;
   1968       result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
   1969       if (sc.Check(soa, false, "i", &result)) {
   1970         return result.i;
   1971       }
   1972     }
   1973     return JNI_ERR;
   1974   }
   1975 
   1976   static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
   1977     ScopedObjectAccess soa(env);
   1978     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1979     JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
   1980     if (sc.Check(soa, true, "ELL", args)) {
   1981       JniValueType result;
   1982       result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
   1983       if (sc.Check(soa, false, "b", &result)) {
   1984         return result.b;
   1985       }
   1986     }
   1987     return JNI_FALSE;
   1988   }
   1989 
   1990   static jobject AllocObject(JNIEnv* env, jclass c) {
   1991     ScopedObjectAccess soa(env);
   1992     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   1993     JniValueType args[2] = {{.E = env}, {.c = c}};
   1994     if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
   1995       JniValueType result;
   1996       result.L = baseEnv(env)->AllocObject(env, c);
   1997       if (sc.Check(soa, false, "L", &result)) {
   1998         return result.L;
   1999       }
   2000     }
   2001     return nullptr;
   2002   }
   2003 
   2004   static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
   2005     ScopedObjectAccess soa(env);
   2006     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2007     VarArgs rest(mid, vargs);
   2008     JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
   2009     if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
   2010         sc.CheckConstructor(mid)) {
   2011       JniValueType result;
   2012       result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
   2013       if (sc.Check(soa, false, "L", &result)) {
   2014         return result.L;
   2015       }
   2016     }
   2017     return nullptr;
   2018   }
   2019 
   2020   static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
   2021     va_list args;
   2022     va_start(args, mid);
   2023     jobject result = NewObjectV(env, c, mid, args);
   2024     va_end(args);
   2025     return result;
   2026   }
   2027 
   2028   static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
   2029     ScopedObjectAccess soa(env);
   2030     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2031     VarArgs rest(mid, vargs);
   2032     JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
   2033     if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
   2034         sc.CheckConstructor(mid)) {
   2035       JniValueType result;
   2036       result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
   2037       if (sc.Check(soa, false, "L", &result)) {
   2038         return result.L;
   2039       }
   2040     }
   2041     return nullptr;
   2042   }
   2043 
   2044   static jclass GetObjectClass(JNIEnv* env, jobject obj) {
   2045     ScopedObjectAccess soa(env);
   2046     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2047     JniValueType args[2] = {{.E = env}, {.L = obj}};
   2048     if (sc.Check(soa, true, "EL", args)) {
   2049       JniValueType result;
   2050       result.c = baseEnv(env)->GetObjectClass(env, obj);
   2051       if (sc.Check(soa, false, "c", &result)) {
   2052         return result.c;
   2053       }
   2054     }
   2055     return nullptr;
   2056   }
   2057 
   2058   static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
   2059     ScopedObjectAccess soa(env);
   2060     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2061     JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
   2062     if (sc.Check(soa, true, "ELc", args)) {
   2063       JniValueType result;
   2064       result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
   2065       if (sc.Check(soa, false, "b", &result)) {
   2066         return result.b;
   2067       }
   2068     }
   2069     return JNI_FALSE;
   2070   }
   2071 
   2072   static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
   2073     return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
   2074   }
   2075 
   2076   static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
   2077     return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
   2078   }
   2079 
   2080   static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
   2081     return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
   2082   }
   2083 
   2084   static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
   2085     return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
   2086   }
   2087 
   2088 #define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
   2089   static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
   2090     return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
   2091   } \
   2092   \
   2093   static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
   2094     return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
   2095   } \
   2096   \
   2097   static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
   2098     JniValueType value; \
   2099     value.shorty = v; \
   2100     SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
   2101   } \
   2102   \
   2103   static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
   2104     JniValueType value; \
   2105     value.shorty = v; \
   2106     SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
   2107   }
   2108 
   2109   FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
   2110   FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
   2111   FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
   2112   FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
   2113   FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
   2114   FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
   2115   FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
   2116   FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
   2117   FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
   2118 #undef FIELD_ACCESSORS
   2119 
   2120   static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
   2121     CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
   2122   }
   2123 
   2124   static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
   2125                                         jvalue* vargs) {
   2126     CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
   2127   }
   2128 
   2129   static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
   2130     CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
   2131   }
   2132 
   2133   static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
   2134     CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
   2135   }
   2136 
   2137   static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
   2138                                         va_list vargs) {
   2139     CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
   2140   }
   2141 
   2142   static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
   2143     CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
   2144   }
   2145 
   2146   static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
   2147     va_list vargs;
   2148     va_start(vargs, mid);
   2149     CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
   2150     va_end(vargs);
   2151   }
   2152 
   2153   static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
   2154     va_list vargs;
   2155     va_start(vargs, mid);
   2156     CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
   2157     va_end(vargs);
   2158   }
   2159 
   2160   static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
   2161     va_list vargs;
   2162     va_start(vargs, mid);
   2163     CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
   2164     va_end(vargs);
   2165   }
   2166 
   2167 #define CALL(rtype, name, ptype, shorty) \
   2168   static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
   2169     return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
   2170   } \
   2171   \
   2172   static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
   2173                                              jvalue* vargs) { \
   2174     return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
   2175   } \
   2176   \
   2177   static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
   2178     return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
   2179   } \
   2180   \
   2181   static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
   2182     return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
   2183   } \
   2184   \
   2185   static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
   2186                                              va_list vargs) { \
   2187     return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
   2188   } \
   2189   \
   2190   static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
   2191     return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
   2192   } \
   2193   \
   2194   static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
   2195     va_list vargs; \
   2196     va_start(vargs, mid); \
   2197     rtype result = \
   2198         CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
   2199     va_end(vargs); \
   2200     return result; \
   2201   } \
   2202   \
   2203   static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
   2204                                             ...) { \
   2205     va_list vargs; \
   2206     va_start(vargs, mid); \
   2207     rtype result = \
   2208         CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
   2209     va_end(vargs); \
   2210     return result; \
   2211   } \
   2212   \
   2213   static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
   2214     va_list vargs; \
   2215     va_start(vargs, mid); \
   2216     rtype result = \
   2217         CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
   2218     va_end(vargs); \
   2219     return result; \
   2220   }
   2221 
   2222   CALL(jobject, Object, Primitive::kPrimNot, L)
   2223   CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
   2224   CALL(jbyte, Byte, Primitive::kPrimByte, B)
   2225   CALL(jchar, Char, Primitive::kPrimChar, C)
   2226   CALL(jshort, Short, Primitive::kPrimShort, S)
   2227   CALL(jint, Int, Primitive::kPrimInt, I)
   2228   CALL(jlong, Long, Primitive::kPrimLong, J)
   2229   CALL(jfloat, Float, Primitive::kPrimFloat, F)
   2230   CALL(jdouble, Double, Primitive::kPrimDouble, D)
   2231 #undef CALL
   2232 
   2233   static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
   2234     ScopedObjectAccess soa(env);
   2235     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2236     JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
   2237     if (sc.Check(soa, true, "Epz", args)) {
   2238       JniValueType result;
   2239       result.s = baseEnv(env)->NewString(env, unicode_chars, len);
   2240       if (sc.Check(soa, false, "s", &result)) {
   2241         return result.s;
   2242       }
   2243     }
   2244     return nullptr;
   2245   }
   2246 
   2247   static jstring NewStringUTF(JNIEnv* env, const char* chars) {
   2248     ScopedObjectAccess soa(env);
   2249     ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
   2250     JniValueType args[2] = {{.E = env}, {.u = chars}};
   2251     if (sc.Check(soa, true, "Eu", args)) {
   2252       JniValueType result;
   2253       // TODO: stale? show pointer and truncate string.
   2254       result.s = baseEnv(env)->NewStringUTF(env, chars);
   2255       if (sc.Check(soa, false, "s", &result)) {
   2256         return result.s;
   2257       }
   2258     }
   2259     return nullptr;
   2260   }
   2261 
   2262   static jsize GetStringLength(JNIEnv* env, jstring string) {
   2263     ScopedObjectAccess soa(env);
   2264     ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
   2265     JniValueType args[2] = {{.E = env}, {.s = string}};
   2266     if (sc.Check(soa, true, "Es", args)) {
   2267       JniValueType result;
   2268       result.z = baseEnv(env)->GetStringLength(env, string);
   2269       if (sc.Check(soa, false, "z", &result)) {
   2270         return result.z;
   2271       }
   2272     }
   2273     return JNI_ERR;
   2274   }
   2275 
   2276   static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
   2277     ScopedObjectAccess soa(env);
   2278     ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
   2279     JniValueType args[2] = {{.E = env}, {.s = string}};
   2280     if (sc.Check(soa, true, "Es", args)) {
   2281       JniValueType result;
   2282       result.z = baseEnv(env)->GetStringUTFLength(env, string);
   2283       if (sc.Check(soa, false, "z", &result)) {
   2284         return result.z;
   2285       }
   2286     }
   2287     return JNI_ERR;
   2288   }
   2289 
   2290   static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
   2291     return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
   2292                                                                  is_copy, false, false));
   2293   }
   2294 
   2295   static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
   2296     return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
   2297                                                                 is_copy, true, false));
   2298   }
   2299 
   2300   static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
   2301     return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
   2302                                                                  is_copy, false, true));
   2303   }
   2304 
   2305   static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
   2306     ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
   2307   }
   2308 
   2309   static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
   2310     ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
   2311   }
   2312 
   2313   static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
   2314     ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
   2315   }
   2316 
   2317   static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
   2318     ScopedObjectAccess soa(env);
   2319     ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
   2320     JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
   2321     // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
   2322     // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
   2323     if (sc.Check(soa, true, "EsIIp", args)) {
   2324       baseEnv(env)->GetStringRegion(env, string, start, len, buf);
   2325       JniValueType result;
   2326       result.V = nullptr;
   2327       sc.Check(soa, false, "V", &result);
   2328     }
   2329   }
   2330 
   2331   static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
   2332     ScopedObjectAccess soa(env);
   2333     ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
   2334     JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
   2335     // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
   2336     // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
   2337     if (sc.Check(soa, true, "EsIIp", args)) {
   2338       baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
   2339       JniValueType result;
   2340       result.V = nullptr;
   2341       sc.Check(soa, false, "V", &result);
   2342     }
   2343   }
   2344 
   2345   static jsize GetArrayLength(JNIEnv* env, jarray array) {
   2346     ScopedObjectAccess soa(env);
   2347     ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
   2348     JniValueType args[2] = {{.E = env}, {.a = array}};
   2349     if (sc.Check(soa, true, "Ea", args)) {
   2350       JniValueType result;
   2351       result.z = baseEnv(env)->GetArrayLength(env, array);
   2352       if (sc.Check(soa, false, "z", &result)) {
   2353         return result.z;
   2354       }
   2355     }
   2356     return JNI_ERR;
   2357   }
   2358 
   2359   static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
   2360                                      jobject initial_element) {
   2361     ScopedObjectAccess soa(env);
   2362     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2363     JniValueType args[4] =
   2364         {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
   2365     if (sc.Check(soa, true, "EzcL", args)) {
   2366       JniValueType result;
   2367       // Note: assignability tests of initial_element are done in the base implementation.
   2368       result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
   2369       if (sc.Check(soa, false, "a", &result)) {
   2370         return down_cast<jobjectArray>(result.a);
   2371       }
   2372     }
   2373     return nullptr;
   2374   }
   2375 
   2376   static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
   2377     ScopedObjectAccess soa(env);
   2378     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2379     JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
   2380     if (sc.Check(soa, true, "Eaz", args)) {
   2381       JniValueType result;
   2382       result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
   2383       if (sc.Check(soa, false, "L", &result)) {
   2384         return result.L;
   2385       }
   2386     }
   2387     return nullptr;
   2388   }
   2389 
   2390   static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
   2391     ScopedObjectAccess soa(env);
   2392     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2393     JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
   2394     // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
   2395     // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
   2396     // in ArrayStoreExceptions.
   2397     if (sc.Check(soa, true, "EaIL", args)) {
   2398       baseEnv(env)->SetObjectArrayElement(env, array, index, value);
   2399       JniValueType result;
   2400       result.V = nullptr;
   2401       sc.Check(soa, false, "V", &result);
   2402     }
   2403   }
   2404 
   2405   static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
   2406     return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
   2407                                                       Primitive::kPrimBoolean));
   2408   }
   2409 
   2410   static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
   2411     return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
   2412                                                    Primitive::kPrimByte));
   2413   }
   2414 
   2415   static jcharArray NewCharArray(JNIEnv* env, jsize length) {
   2416     return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
   2417                                                    Primitive::kPrimChar));
   2418   }
   2419 
   2420   static jshortArray NewShortArray(JNIEnv* env, jsize length) {
   2421     return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
   2422                                                     Primitive::kPrimShort));
   2423   }
   2424 
   2425   static jintArray NewIntArray(JNIEnv* env, jsize length) {
   2426     return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
   2427   }
   2428 
   2429   static jlongArray NewLongArray(JNIEnv* env, jsize length) {
   2430     return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
   2431                                                    Primitive::kPrimLong));
   2432   }
   2433 
   2434   static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
   2435     return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
   2436                                                     Primitive::kPrimFloat));
   2437   }
   2438 
   2439   static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
   2440     return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
   2441                                                      Primitive::kPrimDouble));
   2442   }
   2443 
   2444 // NOLINT added to avoid wrong warning/fix from clang-tidy.
   2445 #define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
   2446   static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
   2447     return reinterpret_cast<ctype*>( /* NOLINT */ \
   2448         GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
   2449   } \
   2450   \
   2451   static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
   2452                                            jint mode) { \
   2453     ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
   2454   } \
   2455   \
   2456   static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
   2457                                      ctype* buf) { /* NOLINT */ \
   2458     GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
   2459   } \
   2460   \
   2461   static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
   2462                                      const ctype* buf) { \
   2463     SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
   2464   }
   2465 
   2466   PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
   2467   PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
   2468   PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
   2469   PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
   2470   PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
   2471   PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
   2472   PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
   2473   PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
   2474 #undef PRIMITIVE_ARRAY_FUNCTIONS
   2475 
   2476   static jint MonitorEnter(JNIEnv* env, jobject obj) {
   2477     ScopedObjectAccess soa(env);
   2478     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2479     JniValueType args[2] = {{.E = env}, {.L = obj}};
   2480     if (sc.Check(soa, true, "EL", args)) {
   2481       if (obj != nullptr) {
   2482         down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
   2483       }
   2484       JniValueType result;
   2485       result.i = baseEnv(env)->MonitorEnter(env, obj);
   2486       if (sc.Check(soa, false, "i", &result)) {
   2487         return result.i;
   2488       }
   2489     }
   2490     return JNI_ERR;
   2491   }
   2492 
   2493   static jint MonitorExit(JNIEnv* env, jobject obj) {
   2494     ScopedObjectAccess soa(env);
   2495     ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
   2496     JniValueType args[2] = {{.E = env}, {.L = obj}};
   2497     if (sc.Check(soa, true, "EL", args)) {
   2498       if (obj != nullptr) {
   2499         down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
   2500       }
   2501       JniValueType result;
   2502       result.i = baseEnv(env)->MonitorExit(env, obj);
   2503       if (sc.Check(soa, false, "i", &result)) {
   2504         return result.i;
   2505       }
   2506     }
   2507     return JNI_ERR;
   2508   }
   2509 
   2510   static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
   2511     ScopedObjectAccess soa(env);
   2512     ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
   2513     JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
   2514     if (sc.Check(soa, true, "Eap", args)) {
   2515       JniValueType result;
   2516       void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
   2517       if (ptr != nullptr && soa.ForceCopy()) {
   2518         ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
   2519       }
   2520       result.p = ptr;
   2521       if (sc.Check(soa, false, "p", &result)) {
   2522         return const_cast<void*>(result.p);
   2523       }
   2524     }
   2525     return nullptr;
   2526   }
   2527 
   2528   static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
   2529     ScopedObjectAccess soa(env);
   2530     ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
   2531     sc.CheckNonNull(carray);
   2532     JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
   2533     if (sc.Check(soa, true, "Eapr", args)) {
   2534       if (soa.ForceCopy()) {
   2535         carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
   2536       }
   2537       baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
   2538       JniValueType result;
   2539       result.V = nullptr;
   2540       sc.Check(soa, false, "V", &result);
   2541     }
   2542   }
   2543 
   2544   static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
   2545     ScopedObjectAccess soa(env);
   2546     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2547     JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
   2548     if (sc.Check(soa, true, "EpJ", args)) {
   2549       JniValueType result;
   2550       // Note: the validity of address and capacity are checked in the base implementation.
   2551       result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
   2552       if (sc.Check(soa, false, "L", &result)) {
   2553         return result.L;
   2554       }
   2555     }
   2556     return nullptr;
   2557   }
   2558 
   2559   static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
   2560     ScopedObjectAccess soa(env);
   2561     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2562     JniValueType args[2] = {{.E = env}, {.L = buf}};
   2563     if (sc.Check(soa, true, "EL", args)) {
   2564       JniValueType result;
   2565       // Note: this is implemented in the base environment by a GetLongField which will sanity
   2566       // check the type of buf in GetLongField above.
   2567       result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
   2568       if (sc.Check(soa, false, "p", &result)) {
   2569         return const_cast<void*>(result.p);
   2570       }
   2571     }
   2572     return nullptr;
   2573   }
   2574 
   2575   static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
   2576     ScopedObjectAccess soa(env);
   2577     ScopedCheck sc(kFlag_Default, __FUNCTION__);
   2578     JniValueType args[2] = {{.E = env}, {.L = buf}};
   2579     if (sc.Check(soa, true, "EL", args)) {
   2580       JniValueType result;
   2581       // Note: this is implemented in the base environment by a GetIntField which will sanity
   2582       // check the type of buf in GetIntField above.
   2583       result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
   2584       if (sc.Check(soa, false, "J", &result)) {
   2585         return result.J;
   2586       }
   2587     }
   2588     return JNI_ERR;
   2589   }
   2590 
   2591  private:
   2592   static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
   2593     return reinterpret_cast<JNIEnvExt*>(env)->vm;
   2594   }
   2595 
   2596   static const JNINativeInterface* baseEnv(JNIEnv* env) {
   2597     return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
   2598   }
   2599 
   2600   static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
   2601     ScopedObjectAccess soa(env);
   2602     ScopedCheck sc(kFlag_Default, function_name);
   2603     JniValueType args[2] = {{.E = env}, {.L = obj}};
   2604     if (sc.Check(soa, true, "EL", args)) {
   2605       JniValueType result;
   2606       switch (kind) {
   2607         case kGlobal:
   2608           result.L = baseEnv(env)->NewGlobalRef(env, obj);
   2609           break;
   2610         case kLocal:
   2611           result.L = baseEnv(env)->NewLocalRef(env, obj);
   2612           break;
   2613         case kWeakGlobal:
   2614           result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
   2615           break;
   2616         default:
   2617           LOG(FATAL) << "Unexpected reference kind: " << kind;
   2618       }
   2619       if (sc.Check(soa, false, "L", &result)) {
   2620         DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
   2621         DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
   2622         return result.L;
   2623       }
   2624     }
   2625     return nullptr;
   2626   }
   2627 
   2628   static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
   2629     ScopedObjectAccess soa(env);
   2630     ScopedCheck sc(kFlag_ExcepOkay, function_name);
   2631     JniValueType args[2] = {{.E = env}, {.L = obj}};
   2632     sc.Check(soa, true, "EL", args);
   2633     if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
   2634       JniValueType result;
   2635       switch (kind) {
   2636         case kGlobal:
   2637           baseEnv(env)->DeleteGlobalRef(env, obj);
   2638           break;
   2639         case kLocal:
   2640           baseEnv(env)->DeleteLocalRef(env, obj);
   2641           break;
   2642         case kWeakGlobal:
   2643           baseEnv(env)->DeleteWeakGlobalRef(env, obj);
   2644           break;
   2645         default:
   2646           LOG(FATAL) << "Unexpected reference kind: " << kind;
   2647       }
   2648       result.V = nullptr;
   2649       sc.Check(soa, false, "V", &result);
   2650     }
   2651   }
   2652 
   2653   static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
   2654                                        const char* name, const char* sig, bool is_static) {
   2655     ScopedObjectAccess soa(env);
   2656     ScopedCheck sc(kFlag_Default, function_name);
   2657     JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
   2658     if (sc.Check(soa, true, "Ecuu", args)) {
   2659       JniValueType result;
   2660       if (is_static) {
   2661         result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
   2662       } else {
   2663         result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
   2664       }
   2665       if (sc.Check(soa, false, "m", &result)) {
   2666         return result.m;
   2667       }
   2668     }
   2669     return nullptr;
   2670   }
   2671 
   2672   static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
   2673                                      const char* name, const char* sig, bool is_static) {
   2674     ScopedObjectAccess soa(env);
   2675     ScopedCheck sc(kFlag_Default, function_name);
   2676     JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
   2677     if (sc.Check(soa, true, "Ecuu", args)) {
   2678       JniValueType result;
   2679       if (is_static) {
   2680         result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
   2681       } else {
   2682         result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
   2683       }
   2684       if (sc.Check(soa, false, "f", &result)) {
   2685         return result.f;
   2686       }
   2687     }
   2688     return nullptr;
   2689   }
   2690 
   2691   static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
   2692                                bool is_static, Primitive::Type type) {
   2693     ScopedObjectAccess soa(env);
   2694     ScopedCheck sc(kFlag_Default, function_name);
   2695     JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
   2696     JniValueType result;
   2697     if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
   2698         sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
   2699       const char* result_check = nullptr;
   2700       switch (type) {
   2701         case Primitive::kPrimNot:
   2702           if (is_static) {
   2703             result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
   2704           } else {
   2705             result.L = baseEnv(env)->GetObjectField(env, obj, fid);
   2706           }
   2707           result_check = "L";
   2708           break;
   2709         case Primitive::kPrimBoolean:
   2710           if (is_static) {
   2711             result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
   2712           } else {
   2713             result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
   2714           }
   2715           result_check = "Z";
   2716           break;
   2717         case Primitive::kPrimByte:
   2718           if (is_static) {
   2719             result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
   2720           } else {
   2721             result.B = baseEnv(env)->GetByteField(env, obj, fid);
   2722           }
   2723           result_check = "B";
   2724           break;
   2725         case Primitive::kPrimChar:
   2726           if (is_static) {
   2727             result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
   2728           } else {
   2729             result.C = baseEnv(env)->GetCharField(env, obj, fid);
   2730           }
   2731           result_check = "C";
   2732           break;
   2733         case Primitive::kPrimShort:
   2734           if (is_static) {
   2735             result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
   2736           } else {
   2737             result.S = baseEnv(env)->GetShortField(env, obj, fid);
   2738           }
   2739           result_check = "S";
   2740           break;
   2741         case Primitive::kPrimInt:
   2742           if (is_static) {
   2743             result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
   2744           } else {
   2745             result.I = baseEnv(env)->GetIntField(env, obj, fid);
   2746           }
   2747           result_check = "I";
   2748           break;
   2749         case Primitive::kPrimLong:
   2750           if (is_static) {
   2751             result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
   2752           } else {
   2753             result.J = baseEnv(env)->GetLongField(env, obj, fid);
   2754           }
   2755           result_check = "J";
   2756           break;
   2757         case Primitive::kPrimFloat:
   2758           if (is_static) {
   2759             result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
   2760           } else {
   2761             result.F = baseEnv(env)->GetFloatField(env, obj, fid);
   2762           }
   2763           result_check = "F";
   2764           break;
   2765         case Primitive::kPrimDouble:
   2766           if (is_static) {
   2767             result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
   2768           } else {
   2769             result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
   2770           }
   2771           result_check = "D";
   2772           break;
   2773         case Primitive::kPrimVoid:
   2774           LOG(FATAL) << "Unexpected type: " << type;
   2775           break;
   2776       }
   2777       if (sc.Check(soa, false, result_check, &result)) {
   2778         return result;
   2779       }
   2780     }
   2781     result.J = 0;
   2782     return result;
   2783   }
   2784 
   2785   static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
   2786                        bool is_static, Primitive::Type type, JniValueType value) {
   2787     ScopedObjectAccess soa(env);
   2788     ScopedCheck sc(kFlag_Default, function_name);
   2789     JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
   2790     char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
   2791         type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
   2792     if (sc.Check(soa, true, sig, args) &&
   2793         sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
   2794       switch (type) {
   2795         case Primitive::kPrimNot:
   2796           if (is_static) {
   2797             baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
   2798           } else {
   2799             baseEnv(env)->SetObjectField(env, obj, fid, value.L);
   2800           }
   2801           break;
   2802         case Primitive::kPrimBoolean:
   2803           if (is_static) {
   2804             baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
   2805           } else {
   2806             baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
   2807           }
   2808           break;
   2809         case Primitive::kPrimByte:
   2810           if (is_static) {
   2811             baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
   2812           } else {
   2813             baseEnv(env)->SetByteField(env, obj, fid, value.B);
   2814           }
   2815           break;
   2816         case Primitive::kPrimChar:
   2817           if (is_static) {
   2818             baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
   2819           } else {
   2820             baseEnv(env)->SetCharField(env, obj, fid, value.C);
   2821           }
   2822           break;
   2823         case Primitive::kPrimShort:
   2824           if (is_static) {
   2825             baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
   2826           } else {
   2827             baseEnv(env)->SetShortField(env, obj, fid, value.S);
   2828           }
   2829           break;
   2830         case Primitive::kPrimInt:
   2831           if (is_static) {
   2832             baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
   2833           } else {
   2834             baseEnv(env)->SetIntField(env, obj, fid, value.I);
   2835           }
   2836           break;
   2837         case Primitive::kPrimLong:
   2838           if (is_static) {
   2839             baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
   2840           } else {
   2841             baseEnv(env)->SetLongField(env, obj, fid, value.J);
   2842           }
   2843           break;
   2844         case Primitive::kPrimFloat:
   2845           if (is_static) {
   2846             baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
   2847           } else {
   2848             baseEnv(env)->SetFloatField(env, obj, fid, value.F);
   2849           }
   2850           break;
   2851         case Primitive::kPrimDouble:
   2852           if (is_static) {
   2853             baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
   2854           } else {
   2855             baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
   2856           }
   2857           break;
   2858         case Primitive::kPrimVoid:
   2859           LOG(FATAL) << "Unexpected type: " << type;
   2860           break;
   2861       }
   2862       JniValueType result;
   2863       result.V = nullptr;
   2864       sc.Check(soa, false, "V", &result);
   2865     }
   2866   }
   2867 
   2868   static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
   2869                             jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
   2870       REQUIRES_SHARED(Locks::mutator_lock_) {
   2871     bool checked;
   2872     switch (invoke) {
   2873       case kVirtual: {
   2874         DCHECK(c == nullptr);
   2875         JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
   2876         checked = sc.Check(soa, true, "ELm.", args);
   2877         break;
   2878       }
   2879       case kDirect: {
   2880         JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
   2881         checked = sc.Check(soa, true, "ELcm.", args);
   2882         break;
   2883       }
   2884       case kStatic: {
   2885         DCHECK(obj == nullptr);
   2886         JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
   2887         checked = sc.Check(soa, true, "Ecm.", args);
   2888         break;
   2889       }
   2890       default:
   2891         LOG(FATAL) << "Unexpected invoke: " << invoke;
   2892         checked = false;
   2893         break;
   2894     }
   2895     return checked;
   2896   }
   2897 
   2898   static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
   2899                                   jmethodID mid, jvalue* vargs, Primitive::Type type,
   2900                                   InvokeType invoke) {
   2901     ScopedObjectAccess soa(env);
   2902     ScopedCheck sc(kFlag_Default, function_name);
   2903     JniValueType result;
   2904     VarArgs rest(mid, vargs);
   2905     if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
   2906         sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
   2907       const char* result_check;
   2908       switch (type) {
   2909         case Primitive::kPrimNot:
   2910           result_check = "L";
   2911           switch (invoke) {
   2912             case kVirtual:
   2913               result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
   2914               break;
   2915             case kDirect:
   2916               result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
   2917               break;
   2918             case kStatic:
   2919               result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
   2920               break;
   2921             default:
   2922               break;
   2923           }
   2924           break;
   2925         case Primitive::kPrimBoolean:
   2926           result_check = "Z";
   2927           switch (invoke) {
   2928             case kVirtual:
   2929               result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
   2930               break;
   2931             case kDirect:
   2932               result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
   2933               break;
   2934             case kStatic:
   2935               result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
   2936               break;
   2937             default:
   2938               break;
   2939           }
   2940           break;
   2941         case Primitive::kPrimByte:
   2942           result_check = "B";
   2943           switch (invoke) {
   2944             case kVirtual:
   2945               result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
   2946               break;
   2947             case kDirect:
   2948               result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
   2949               break;
   2950             case kStatic:
   2951               result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
   2952               break;
   2953             default:
   2954               break;
   2955           }
   2956           break;
   2957         case Primitive::kPrimChar:
   2958           result_check = "C";
   2959           switch (invoke) {
   2960             case kVirtual:
   2961               result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
   2962               break;
   2963             case kDirect:
   2964               result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
   2965               break;
   2966             case kStatic:
   2967               result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
   2968               break;
   2969             default:
   2970               break;
   2971           }
   2972           break;
   2973         case Primitive::kPrimShort:
   2974           result_check = "S";
   2975           switch (invoke) {
   2976             case kVirtual:
   2977               result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
   2978               break;
   2979             case kDirect:
   2980               result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
   2981               break;
   2982             case kStatic:
   2983               result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
   2984               break;
   2985             default:
   2986               break;
   2987           }
   2988           break;
   2989         case Primitive::kPrimInt:
   2990           result_check = "I";
   2991           switch (invoke) {
   2992             case kVirtual:
   2993               result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
   2994               break;
   2995             case kDirect:
   2996               result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
   2997               break;
   2998             case kStatic:
   2999               result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
   3000               break;
   3001             default:
   3002               break;
   3003           }
   3004           break;
   3005         case Primitive::kPrimLong:
   3006           result_check = "J";
   3007           switch (invoke) {
   3008             case kVirtual:
   3009               result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
   3010               break;
   3011             case kDirect:
   3012               result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
   3013               break;
   3014             case kStatic:
   3015               result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
   3016               break;
   3017             default:
   3018               break;
   3019           }
   3020           break;
   3021         case Primitive::kPrimFloat:
   3022           result_check = "F";
   3023           switch (invoke) {
   3024             case kVirtual:
   3025               result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
   3026               break;
   3027             case kDirect:
   3028               result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
   3029               break;
   3030             case kStatic:
   3031               result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
   3032               break;
   3033             default:
   3034               break;
   3035           }
   3036           break;
   3037         case Primitive::kPrimDouble:
   3038           result_check = "D";
   3039           switch (invoke) {
   3040             case kVirtual:
   3041               result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
   3042               break;
   3043             case kDirect:
   3044               result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
   3045               break;
   3046             case kStatic:
   3047               result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
   3048               break;
   3049             default:
   3050               break;
   3051           }
   3052           break;
   3053         case Primitive::kPrimVoid:
   3054           result_check = "V";
   3055           result.V = nullptr;
   3056           switch (invoke) {
   3057             case kVirtual:
   3058               baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
   3059               break;
   3060             case kDirect:
   3061               baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
   3062               break;
   3063             case kStatic:
   3064               baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
   3065               break;
   3066             default:
   3067               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3068           }
   3069           break;
   3070         default:
   3071           LOG(FATAL) << "Unexpected return type: " << type;
   3072           result_check = nullptr;
   3073       }
   3074       if (sc.Check(soa, false, result_check, &result)) {
   3075         return result;
   3076       }
   3077     }
   3078     result.J = 0;
   3079     return result;
   3080   }
   3081 
   3082   static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
   3083                                   jmethodID mid, va_list vargs, Primitive::Type type,
   3084                                   InvokeType invoke) {
   3085     ScopedObjectAccess soa(env);
   3086     ScopedCheck sc(kFlag_Default, function_name);
   3087     JniValueType result;
   3088     VarArgs rest(mid, vargs);
   3089     if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
   3090         sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
   3091       const char* result_check;
   3092       switch (type) {
   3093         case Primitive::kPrimNot:
   3094           result_check = "L";
   3095           switch (invoke) {
   3096             case kVirtual:
   3097               result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
   3098               break;
   3099             case kDirect:
   3100               result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
   3101               break;
   3102             case kStatic:
   3103               result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
   3104               break;
   3105             default:
   3106               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3107           }
   3108           break;
   3109         case Primitive::kPrimBoolean:
   3110           result_check = "Z";
   3111           switch (invoke) {
   3112             case kVirtual:
   3113               result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
   3114               break;
   3115             case kDirect:
   3116               result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
   3117               break;
   3118             case kStatic:
   3119               result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
   3120               break;
   3121             default:
   3122               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3123           }
   3124           break;
   3125         case Primitive::kPrimByte:
   3126           result_check = "B";
   3127           switch (invoke) {
   3128             case kVirtual:
   3129               result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
   3130               break;
   3131             case kDirect:
   3132               result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
   3133               break;
   3134             case kStatic:
   3135               result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
   3136               break;
   3137             default:
   3138               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3139           }
   3140           break;
   3141         case Primitive::kPrimChar:
   3142           result_check = "C";
   3143           switch (invoke) {
   3144             case kVirtual:
   3145               result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
   3146               break;
   3147             case kDirect:
   3148               result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
   3149               break;
   3150             case kStatic:
   3151               result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
   3152               break;
   3153             default:
   3154               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3155           }
   3156           break;
   3157         case Primitive::kPrimShort:
   3158           result_check = "S";
   3159           switch (invoke) {
   3160             case kVirtual:
   3161               result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
   3162               break;
   3163             case kDirect:
   3164               result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
   3165               break;
   3166             case kStatic:
   3167               result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
   3168               break;
   3169             default:
   3170               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3171           }
   3172           break;
   3173         case Primitive::kPrimInt:
   3174           result_check = "I";
   3175           switch (invoke) {
   3176             case kVirtual:
   3177               result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
   3178               break;
   3179             case kDirect:
   3180               result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
   3181               break;
   3182             case kStatic:
   3183               result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
   3184               break;
   3185             default:
   3186               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3187           }
   3188           break;
   3189         case Primitive::kPrimLong:
   3190           result_check = "J";
   3191           switch (invoke) {
   3192             case kVirtual:
   3193               result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
   3194               break;
   3195             case kDirect:
   3196               result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
   3197               break;
   3198             case kStatic:
   3199               result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
   3200               break;
   3201             default:
   3202               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3203           }
   3204           break;
   3205         case Primitive::kPrimFloat:
   3206           result_check = "F";
   3207           switch (invoke) {
   3208             case kVirtual:
   3209               result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
   3210               break;
   3211             case kDirect:
   3212               result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
   3213               break;
   3214             case kStatic:
   3215               result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
   3216               break;
   3217             default:
   3218               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3219           }
   3220           break;
   3221         case Primitive::kPrimDouble:
   3222           result_check = "D";
   3223           switch (invoke) {
   3224             case kVirtual:
   3225               result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
   3226               break;
   3227             case kDirect:
   3228               result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
   3229               break;
   3230             case kStatic:
   3231               result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
   3232               break;
   3233             default:
   3234               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3235           }
   3236           break;
   3237         case Primitive::kPrimVoid:
   3238           result_check = "V";
   3239           result.V = nullptr;
   3240           switch (invoke) {
   3241             case kVirtual:
   3242               baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
   3243               break;
   3244             case kDirect:
   3245               baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
   3246               break;
   3247             case kStatic:
   3248               baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
   3249               break;
   3250             default:
   3251               LOG(FATAL) << "Unexpected invoke: " << invoke;
   3252           }
   3253           break;
   3254         default:
   3255           LOG(FATAL) << "Unexpected return type: " << type;
   3256           result_check = nullptr;
   3257       }
   3258       if (sc.Check(soa, false, result_check, &result)) {
   3259         return result;
   3260       }
   3261     }
   3262     result.J = 0;
   3263     return result;
   3264   }
   3265 
   3266   static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
   3267                                             jboolean* is_copy, bool utf, bool critical) {
   3268     ScopedObjectAccess soa(env);
   3269     int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
   3270     ScopedCheck sc(flags, function_name);
   3271     JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
   3272     if (sc.Check(soa, true, "Esp", args)) {
   3273       JniValueType result;
   3274       void* ptr;
   3275       if (utf) {
   3276         CHECK(!critical);
   3277         ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
   3278         result.u = reinterpret_cast<char*>(ptr);
   3279       } else {
   3280         ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
   3281             baseEnv(env)->GetStringChars(env, string, is_copy));
   3282         result.p = ptr;
   3283       }
   3284       // TODO: could we be smarter about not copying when local_is_copy?
   3285       if (ptr != nullptr && soa.ForceCopy()) {
   3286         if (utf) {
   3287           size_t length_in_bytes = strlen(result.u) + 1;
   3288           result.u =
   3289               reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
   3290         } else {
   3291           size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
   3292           result.p =
   3293               reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
   3294         }
   3295         if (is_copy != nullptr) {
   3296           *is_copy = JNI_TRUE;
   3297         }
   3298       }
   3299       if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
   3300         return utf ? result.u : result.p;
   3301       }
   3302     }
   3303     return nullptr;
   3304   }
   3305 
   3306   static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
   3307                                          const void* chars, bool utf, bool critical) {
   3308     ScopedObjectAccess soa(env);
   3309     int flags = kFlag_ExcepOkay | kFlag_Release;
   3310     if (critical) {
   3311       flags |= kFlag_CritRelease;
   3312     }
   3313     ScopedCheck sc(flags, function_name);
   3314     sc.CheckNonNull(chars);
   3315     bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
   3316     if (force_copy_ok && soa.ForceCopy()) {
   3317       chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
   3318     }
   3319     if (force_copy_ok) {
   3320       JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
   3321       if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
   3322         if (utf) {
   3323           CHECK(!critical);
   3324           baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
   3325         } else {
   3326           if (critical) {
   3327             baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
   3328           } else {
   3329             baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
   3330           }
   3331         }
   3332         JniValueType result;
   3333         sc.Check(soa, false, "V", &result);
   3334       }
   3335     }
   3336   }
   3337 
   3338   static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
   3339                                   Primitive::Type type) {
   3340     ScopedObjectAccess soa(env);
   3341     ScopedCheck sc(kFlag_Default, function_name);
   3342     JniValueType args[2] = {{.E = env}, {.z = length}};
   3343     if (sc.Check(soa, true, "Ez", args)) {
   3344       JniValueType result;
   3345       switch (type) {
   3346         case Primitive::kPrimBoolean:
   3347           result.a = baseEnv(env)->NewBooleanArray(env, length);
   3348           break;
   3349         case Primitive::kPrimByte:
   3350           result.a = baseEnv(env)->NewByteArray(env, length);
   3351           break;
   3352         case Primitive::kPrimChar:
   3353           result.a = baseEnv(env)->NewCharArray(env, length);
   3354           break;
   3355         case Primitive::kPrimShort:
   3356           result.a = baseEnv(env)->NewShortArray(env, length);
   3357           break;
   3358         case Primitive::kPrimInt:
   3359           result.a = baseEnv(env)->NewIntArray(env, length);
   3360           break;
   3361         case Primitive::kPrimLong:
   3362           result.a = baseEnv(env)->NewLongArray(env, length);
   3363           break;
   3364         case Primitive::kPrimFloat:
   3365           result.a = baseEnv(env)->NewFloatArray(env, length);
   3366           break;
   3367         case Primitive::kPrimDouble:
   3368           result.a = baseEnv(env)->NewDoubleArray(env, length);
   3369           break;
   3370         default:
   3371           LOG(FATAL) << "Unexpected primitive type: " << type;
   3372       }
   3373       if (sc.Check(soa, false, "a", &result)) {
   3374         return result.a;
   3375       }
   3376     }
   3377     return nullptr;
   3378   }
   3379 
   3380   static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
   3381                                          JNIEnv* env, jarray array, jboolean* is_copy) {
   3382     ScopedObjectAccess soa(env);
   3383     ScopedCheck sc(kFlag_Default, function_name);
   3384     JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
   3385     if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
   3386       JniValueType result;
   3387       void* ptr = nullptr;
   3388       switch (type) {
   3389         case Primitive::kPrimBoolean:
   3390           ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
   3391                                                       is_copy);
   3392           break;
   3393         case Primitive::kPrimByte:
   3394           ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
   3395           break;
   3396         case Primitive::kPrimChar:
   3397           ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
   3398           break;
   3399         case Primitive::kPrimShort:
   3400           ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
   3401           break;
   3402         case Primitive::kPrimInt:
   3403           ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
   3404           break;
   3405         case Primitive::kPrimLong:
   3406           ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
   3407           break;
   3408         case Primitive::kPrimFloat:
   3409           ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
   3410           break;
   3411         case Primitive::kPrimDouble:
   3412           ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
   3413           break;
   3414         default:
   3415           LOG(FATAL) << "Unexpected primitive type: " << type;
   3416       }
   3417       if (ptr != nullptr && soa.ForceCopy()) {
   3418         ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
   3419         if (is_copy != nullptr) {
   3420           *is_copy = JNI_TRUE;
   3421         }
   3422       }
   3423       result.p = ptr;
   3424       if (sc.Check(soa, false, "p", &result)) {
   3425         return const_cast<void*>(result.p);
   3426       }
   3427     }
   3428     return nullptr;
   3429   }
   3430 
   3431   static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
   3432                                             JNIEnv* env, jarray array, void* elems, jint mode) {
   3433     ScopedObjectAccess soa(env);
   3434     ScopedCheck sc(kFlag_ExcepOkay, function_name);
   3435     if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
   3436       if (soa.ForceCopy()) {
   3437         elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
   3438       }
   3439       if (!soa.ForceCopy() || elems != nullptr) {
   3440         JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
   3441         if (sc.Check(soa, true, "Eapr", args)) {
   3442           switch (type) {
   3443             case Primitive::kPrimBoolean:
   3444               baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
   3445                                                         reinterpret_cast<jboolean*>(elems), mode);
   3446               break;
   3447             case Primitive::kPrimByte:
   3448               baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
   3449                                                      reinterpret_cast<jbyte*>(elems), mode);
   3450               break;
   3451             case Primitive::kPrimChar:
   3452               baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
   3453                                                      reinterpret_cast<jchar*>(elems), mode);
   3454               break;
   3455             case Primitive::kPrimShort:
   3456               baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
   3457                                                       reinterpret_cast<jshort*>(elems), mode);
   3458               break;
   3459             case Primitive::kPrimInt:
   3460               baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
   3461                                                     reinterpret_cast<jint*>(elems), mode);
   3462               break;
   3463             case Primitive::kPrimLong:
   3464               baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
   3465                                                      reinterpret_cast<jlong*>(elems), mode);
   3466               break;
   3467             case Primitive::kPrimFloat:
   3468               baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
   3469                                                       reinterpret_cast<jfloat*>(elems), mode);
   3470               break;
   3471             case Primitive::kPrimDouble:
   3472               baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
   3473                                                        reinterpret_cast<jdouble*>(elems), mode);
   3474               break;
   3475             default:
   3476               LOG(FATAL) << "Unexpected primitive type: " << type;
   3477           }
   3478           JniValueType result;
   3479           result.V = nullptr;
   3480           sc.Check(soa, false, "V", &result);
   3481         }
   3482       }
   3483     }
   3484   }
   3485 
   3486   static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
   3487                                       jarray array, jsize start, jsize len, void* buf) {
   3488     ScopedObjectAccess soa(env);
   3489     ScopedCheck sc(kFlag_Default, function_name);
   3490     JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
   3491     // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
   3492     // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
   3493     if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
   3494       switch (type) {
   3495         case Primitive::kPrimBoolean:
   3496           baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
   3497                                               reinterpret_cast<jboolean*>(buf));
   3498           break;
   3499         case Primitive::kPrimByte:
   3500           baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
   3501                                            reinterpret_cast<jbyte*>(buf));
   3502           break;
   3503         case Primitive::kPrimChar:
   3504           baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
   3505                                            reinterpret_cast<jchar*>(buf));
   3506           break;
   3507         case Primitive::kPrimShort:
   3508           baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
   3509                                             reinterpret_cast<jshort*>(buf));
   3510           break;
   3511         case Primitive::kPrimInt:
   3512           baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
   3513                                           reinterpret_cast<jint*>(buf));
   3514           break;
   3515         case Primitive::kPrimLong:
   3516           baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
   3517                                            reinterpret_cast<jlong*>(buf));
   3518           break;
   3519         case Primitive::kPrimFloat:
   3520           baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
   3521                                             reinterpret_cast<jfloat*>(buf));
   3522           break;
   3523         case Primitive::kPrimDouble:
   3524           baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
   3525                                              reinterpret_cast<jdouble*>(buf));
   3526           break;
   3527         default:
   3528           LOG(FATAL) << "Unexpected primitive type: " << type;
   3529       }
   3530       JniValueType result;
   3531       result.V = nullptr;
   3532       sc.Check(soa, false, "V", &result);
   3533     }
   3534   }
   3535 
   3536   static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
   3537                                       jarray array, jsize start, jsize len, const void* buf) {
   3538     ScopedObjectAccess soa(env);
   3539     ScopedCheck sc(kFlag_Default, function_name);
   3540     JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
   3541     // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
   3542     // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
   3543     if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
   3544       switch (type) {
   3545         case Primitive::kPrimBoolean:
   3546           baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
   3547                                               reinterpret_cast<const jboolean*>(buf));
   3548           break;
   3549         case Primitive::kPrimByte:
   3550           baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
   3551                                            reinterpret_cast<const jbyte*>(buf));
   3552           break;
   3553         case Primitive::kPrimChar:
   3554           baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
   3555                                            reinterpret_cast<const jchar*>(buf));
   3556           break;
   3557         case Primitive::kPrimShort:
   3558           baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
   3559                                               reinterpret_cast<const jshort*>(buf));
   3560           break;
   3561         case Primitive::kPrimInt:
   3562           baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
   3563                                           reinterpret_cast<const jint*>(buf));
   3564           break;
   3565         case Primitive::kPrimLong:
   3566           baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
   3567                                               reinterpret_cast<const jlong*>(buf));
   3568           break;
   3569         case Primitive::kPrimFloat:
   3570           baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
   3571                                             reinterpret_cast<const jfloat*>(buf));
   3572           break;
   3573         case Primitive::kPrimDouble:
   3574           baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
   3575                                              reinterpret_cast<const jdouble*>(buf));
   3576           break;
   3577         default:
   3578           LOG(FATAL) << "Unexpected primitive type: " << type;
   3579       }
   3580       JniValueType result;
   3581       result.V = nullptr;
   3582       sc.Check(soa, false, "V", &result);
   3583     }
   3584   }
   3585 };
   3586 
   3587 const JNINativeInterface gCheckNativeInterface = {
   3588   nullptr,  // reserved0.
   3589   nullptr,  // reserved1.
   3590   nullptr,  // reserved2.
   3591   nullptr,  // reserved3.
   3592   CheckJNI::GetVersion,
   3593   CheckJNI::DefineClass,
   3594   CheckJNI::FindClass,
   3595   CheckJNI::FromReflectedMethod,
   3596   CheckJNI::FromReflectedField,
   3597   CheckJNI::ToReflectedMethod,
   3598   CheckJNI::GetSuperclass,
   3599   CheckJNI::IsAssignableFrom,
   3600   CheckJNI::ToReflectedField,
   3601   CheckJNI::Throw,
   3602   CheckJNI::ThrowNew,
   3603   CheckJNI::ExceptionOccurred,
   3604   CheckJNI::ExceptionDescribe,
   3605   CheckJNI::ExceptionClear,
   3606   CheckJNI::FatalError,
   3607   CheckJNI::PushLocalFrame,
   3608   CheckJNI::PopLocalFrame,
   3609   CheckJNI::NewGlobalRef,
   3610   CheckJNI::DeleteGlobalRef,
   3611   CheckJNI::DeleteLocalRef,
   3612   CheckJNI::IsSameObject,
   3613   CheckJNI::NewLocalRef,
   3614   CheckJNI::EnsureLocalCapacity,
   3615   CheckJNI::AllocObject,
   3616   CheckJNI::NewObject,
   3617   CheckJNI::NewObjectV,
   3618   CheckJNI::NewObjectA,
   3619   CheckJNI::GetObjectClass,
   3620   CheckJNI::IsInstanceOf,
   3621   CheckJNI::GetMethodID,
   3622   CheckJNI::CallObjectMethod,
   3623   CheckJNI::CallObjectMethodV,
   3624   CheckJNI::CallObjectMethodA,
   3625   CheckJNI::CallBooleanMethod,
   3626   CheckJNI::CallBooleanMethodV,
   3627   CheckJNI::CallBooleanMethodA,
   3628   CheckJNI::CallByteMethod,
   3629   CheckJNI::CallByteMethodV,
   3630   CheckJNI::CallByteMethodA,
   3631   CheckJNI::CallCharMethod,
   3632   CheckJNI::CallCharMethodV,
   3633   CheckJNI::CallCharMethodA,
   3634   CheckJNI::CallShortMethod,
   3635   CheckJNI::CallShortMethodV,
   3636   CheckJNI::CallShortMethodA,
   3637   CheckJNI::CallIntMethod,
   3638   CheckJNI::CallIntMethodV,
   3639   CheckJNI::CallIntMethodA,
   3640   CheckJNI::CallLongMethod,
   3641   CheckJNI::CallLongMethodV,
   3642   CheckJNI::CallLongMethodA,
   3643   CheckJNI::CallFloatMethod,
   3644   CheckJNI::CallFloatMethodV,
   3645   CheckJNI::CallFloatMethodA,
   3646   CheckJNI::CallDoubleMethod,
   3647   CheckJNI::CallDoubleMethodV,
   3648   CheckJNI::CallDoubleMethodA,
   3649   CheckJNI::CallVoidMethod,
   3650   CheckJNI::CallVoidMethodV,
   3651   CheckJNI::CallVoidMethodA,
   3652   CheckJNI::CallNonvirtualObjectMethod,
   3653   CheckJNI::CallNonvirtualObjectMethodV,
   3654   CheckJNI::CallNonvirtualObjectMethodA,
   3655   CheckJNI::CallNonvirtualBooleanMethod,
   3656   CheckJNI::CallNonvirtualBooleanMethodV,
   3657   CheckJNI::CallNonvirtualBooleanMethodA,
   3658   CheckJNI::CallNonvirtualByteMethod,
   3659   CheckJNI::CallNonvirtualByteMethodV,
   3660   CheckJNI::CallNonvirtualByteMethodA,
   3661   CheckJNI::CallNonvirtualCharMethod,
   3662   CheckJNI::CallNonvirtualCharMethodV,
   3663   CheckJNI::CallNonvirtualCharMethodA,
   3664   CheckJNI::CallNonvirtualShortMethod,
   3665   CheckJNI::CallNonvirtualShortMethodV,
   3666   CheckJNI::CallNonvirtualShortMethodA,
   3667   CheckJNI::CallNonvirtualIntMethod,
   3668   CheckJNI::CallNonvirtualIntMethodV,
   3669   CheckJNI::CallNonvirtualIntMethodA,
   3670   CheckJNI::CallNonvirtualLongMethod,
   3671   CheckJNI::CallNonvirtualLongMethodV,
   3672   CheckJNI::CallNonvirtualLongMethodA,
   3673   CheckJNI::CallNonvirtualFloatMethod,
   3674   CheckJNI::CallNonvirtualFloatMethodV,
   3675   CheckJNI::CallNonvirtualFloatMethodA,
   3676   CheckJNI::CallNonvirtualDoubleMethod,
   3677   CheckJNI::CallNonvirtualDoubleMethodV,
   3678   CheckJNI::CallNonvirtualDoubleMethodA,
   3679   CheckJNI::CallNonvirtualVoidMethod,
   3680   CheckJNI::CallNonvirtualVoidMethodV,
   3681   CheckJNI::CallNonvirtualVoidMethodA,
   3682   CheckJNI::GetFieldID,
   3683   CheckJNI::GetObjectField,
   3684   CheckJNI::GetBooleanField,
   3685   CheckJNI::GetByteField,
   3686   CheckJNI::GetCharField,
   3687   CheckJNI::GetShortField,
   3688   CheckJNI::GetIntField,
   3689   CheckJNI::GetLongField,
   3690   CheckJNI::GetFloatField,
   3691   CheckJNI::GetDoubleField,
   3692   CheckJNI::SetObjectField,
   3693   CheckJNI::SetBooleanField,
   3694   CheckJNI::SetByteField,
   3695   CheckJNI::SetCharField,
   3696   CheckJNI::SetShortField,
   3697   CheckJNI::SetIntField,
   3698   CheckJNI::SetLongField,
   3699   CheckJNI::SetFloatField,
   3700   CheckJNI::SetDoubleField,
   3701   CheckJNI::GetStaticMethodID,
   3702   CheckJNI::CallStaticObjectMethod,
   3703   CheckJNI::CallStaticObjectMethodV,
   3704   CheckJNI::CallStaticObjectMethodA,
   3705   CheckJNI::CallStaticBooleanMethod,
   3706   CheckJNI::CallStaticBooleanMethodV,
   3707   CheckJNI::CallStaticBooleanMethodA,
   3708   CheckJNI::CallStaticByteMethod,
   3709   CheckJNI::CallStaticByteMethodV,
   3710   CheckJNI::CallStaticByteMethodA,
   3711   CheckJNI::CallStaticCharMethod,
   3712   CheckJNI::CallStaticCharMethodV,
   3713   CheckJNI::CallStaticCharMethodA,
   3714   CheckJNI::CallStaticShortMethod,
   3715   CheckJNI::CallStaticShortMethodV,
   3716   CheckJNI::CallStaticShortMethodA,
   3717   CheckJNI::CallStaticIntMethod,
   3718   CheckJNI::CallStaticIntMethodV,
   3719   CheckJNI::CallStaticIntMethodA,
   3720   CheckJNI::CallStaticLongMethod,
   3721   CheckJNI::CallStaticLongMethodV,
   3722   CheckJNI::CallStaticLongMethodA,
   3723   CheckJNI::CallStaticFloatMethod,
   3724   CheckJNI::CallStaticFloatMethodV,
   3725   CheckJNI::CallStaticFloatMethodA,
   3726   CheckJNI::CallStaticDoubleMethod,
   3727   CheckJNI::CallStaticDoubleMethodV,
   3728   CheckJNI::CallStaticDoubleMethodA,
   3729   CheckJNI::CallStaticVoidMethod,
   3730   CheckJNI::CallStaticVoidMethodV,
   3731   CheckJNI::CallStaticVoidMethodA,
   3732   CheckJNI::GetStaticFieldID,
   3733   CheckJNI::GetStaticObjectField,
   3734   CheckJNI::GetStaticBooleanField,
   3735   CheckJNI::GetStaticByteField,
   3736   CheckJNI::GetStaticCharField,
   3737   CheckJNI::GetStaticShortField,
   3738   CheckJNI::GetStaticIntField,
   3739   CheckJNI::GetStaticLongField,
   3740   CheckJNI::GetStaticFloatField,
   3741   CheckJNI::GetStaticDoubleField,
   3742   CheckJNI::SetStaticObjectField,
   3743   CheckJNI::SetStaticBooleanField,
   3744   CheckJNI::SetStaticByteField,
   3745   CheckJNI::SetStaticCharField,
   3746   CheckJNI::SetStaticShortField,
   3747   CheckJNI::SetStaticIntField,
   3748   CheckJNI::SetStaticLongField,
   3749   CheckJNI::SetStaticFloatField,
   3750   CheckJNI::SetStaticDoubleField,
   3751   CheckJNI::NewString,
   3752   CheckJNI::GetStringLength,
   3753   CheckJNI::GetStringChars,
   3754   CheckJNI::ReleaseStringChars,
   3755   CheckJNI::NewStringUTF,
   3756   CheckJNI::GetStringUTFLength,
   3757   CheckJNI::GetStringUTFChars,
   3758   CheckJNI::ReleaseStringUTFChars,
   3759   CheckJNI::GetArrayLength,
   3760   CheckJNI::NewObjectArray,
   3761   CheckJNI::GetObjectArrayElement,
   3762   CheckJNI::SetObjectArrayElement,
   3763   CheckJNI::NewBooleanArray,
   3764   CheckJNI::NewByteArray,
   3765   CheckJNI::NewCharArray,
   3766   CheckJNI::NewShortArray,
   3767   CheckJNI::NewIntArray,
   3768   CheckJNI::NewLongArray,
   3769   CheckJNI::NewFloatArray,
   3770   CheckJNI::NewDoubleArray,
   3771   CheckJNI::GetBooleanArrayElements,
   3772   CheckJNI::GetByteArrayElements,
   3773   CheckJNI::GetCharArrayElements,
   3774   CheckJNI::GetShortArrayElements,
   3775   CheckJNI::GetIntArrayElements,
   3776   CheckJNI::GetLongArrayElements,
   3777   CheckJNI::GetFloatArrayElements,
   3778   CheckJNI::GetDoubleArrayElements,
   3779   CheckJNI::ReleaseBooleanArrayElements,
   3780   CheckJNI::ReleaseByteArrayElements,
   3781   CheckJNI::ReleaseCharArrayElements,
   3782   CheckJNI::ReleaseShortArrayElements,
   3783   CheckJNI::ReleaseIntArrayElements,
   3784   CheckJNI::ReleaseLongArrayElements,
   3785   CheckJNI::ReleaseFloatArrayElements,
   3786   CheckJNI::ReleaseDoubleArrayElements,
   3787   CheckJNI::GetBooleanArrayRegion,
   3788   CheckJNI::GetByteArrayRegion,
   3789   CheckJNI::GetCharArrayRegion,
   3790   CheckJNI::GetShortArrayRegion,
   3791   CheckJNI::GetIntArrayRegion,
   3792   CheckJNI::GetLongArrayRegion,
   3793   CheckJNI::GetFloatArrayRegion,
   3794   CheckJNI::GetDoubleArrayRegion,
   3795   CheckJNI::SetBooleanArrayRegion,
   3796   CheckJNI::SetByteArrayRegion,
   3797   CheckJNI::SetCharArrayRegion,
   3798   CheckJNI::SetShortArrayRegion,
   3799   CheckJNI::SetIntArrayRegion,
   3800   CheckJNI::SetLongArrayRegion,
   3801   CheckJNI::SetFloatArrayRegion,
   3802   CheckJNI::SetDoubleArrayRegion,
   3803   CheckJNI::RegisterNatives,
   3804   CheckJNI::UnregisterNatives,
   3805   CheckJNI::MonitorEnter,
   3806   CheckJNI::MonitorExit,
   3807   CheckJNI::GetJavaVM,
   3808   CheckJNI::GetStringRegion,
   3809   CheckJNI::GetStringUTFRegion,
   3810   CheckJNI::GetPrimitiveArrayCritical,
   3811   CheckJNI::ReleasePrimitiveArrayCritical,
   3812   CheckJNI::GetStringCritical,
   3813   CheckJNI::ReleaseStringCritical,
   3814   CheckJNI::NewWeakGlobalRef,
   3815   CheckJNI::DeleteWeakGlobalRef,
   3816   CheckJNI::ExceptionCheck,
   3817   CheckJNI::NewDirectByteBuffer,
   3818   CheckJNI::GetDirectBufferAddress,
   3819   CheckJNI::GetDirectBufferCapacity,
   3820   CheckJNI::GetObjectRefType,
   3821 };
   3822 
   3823 const JNINativeInterface* GetCheckJniNativeInterface() {
   3824   return &gCheckNativeInterface;
   3825 }
   3826 
   3827 class CheckJII {
   3828  public:
   3829   static jint DestroyJavaVM(JavaVM* vm) {
   3830     ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
   3831     JniValueType args[1] = {{.v = vm}};
   3832     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
   3833     JniValueType result;
   3834     result.i = BaseVm(vm)->DestroyJavaVM(vm);
   3835     // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
   3836     // which will delete the JavaVMExt.
   3837     sc.CheckNonHeap(nullptr, false, "i", &result);
   3838     return result.i;
   3839   }
   3840 
   3841   static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
   3842     ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
   3843     JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
   3844     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
   3845     JniValueType result;
   3846     result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
   3847     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
   3848     return result.i;
   3849   }
   3850 
   3851   static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
   3852     ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
   3853     JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
   3854     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
   3855     JniValueType result;
   3856     result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
   3857     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
   3858     return result.i;
   3859   }
   3860 
   3861   static jint DetachCurrentThread(JavaVM* vm) {
   3862     ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
   3863     JniValueType args[1] = {{.v = vm}};
   3864     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
   3865     JniValueType result;
   3866     result.i = BaseVm(vm)->DetachCurrentThread(vm);
   3867     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
   3868     return result.i;
   3869   }
   3870 
   3871   static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
   3872     ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
   3873     JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
   3874     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
   3875     JniValueType result;
   3876     result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
   3877     sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
   3878     return result.i;
   3879   }
   3880 
   3881  private:
   3882   static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
   3883     return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
   3884   }
   3885 };
   3886 
   3887 const JNIInvokeInterface gCheckInvokeInterface = {
   3888   nullptr,  // reserved0
   3889   nullptr,  // reserved1
   3890   nullptr,  // reserved2
   3891   CheckJII::DestroyJavaVM,
   3892   CheckJII::AttachCurrentThread,
   3893   CheckJII::DetachCurrentThread,
   3894   CheckJII::GetEnv,
   3895   CheckJII::AttachCurrentThreadAsDaemon
   3896 };
   3897 
   3898 const JNIInvokeInterface* GetCheckJniInvokeInterface() {
   3899   return &gCheckInvokeInterface;
   3900 }
   3901 
   3902 }  // namespace art
   3903