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