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