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