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