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