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