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