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