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