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