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