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