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