• 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 "jni_internal.h"
18 
19 #include <sys/mman.h>
20 #include <zlib.h>
21 
22 #include "base/logging.h"
23 #include "class_linker.h"
24 #include "class_linker-inl.h"
25 #include "dex_file-inl.h"
26 #include "gc/space/space.h"
27 #include "mirror/art_field-inl.h"
28 #include "mirror/art_method-inl.h"
29 #include "mirror/class-inl.h"
30 #include "mirror/object-inl.h"
31 #include "mirror/object_array-inl.h"
32 #include "mirror/throwable.h"
33 #include "object_utils.h"
34 #include "runtime.h"
35 #include "scoped_thread_state_change.h"
36 #include "thread.h"
37 
38 namespace art {
39 
JniAbort(const char * jni_function_name,const char * msg)40 static void JniAbort(const char* jni_function_name, const char* msg) {
41   Thread* self = Thread::Current();
42   ScopedObjectAccess soa(self);
43   mirror::ArtMethod* current_method = self->GetCurrentMethod(NULL);
44 
45   std::ostringstream os;
46   os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
47 
48   if (jni_function_name != NULL) {
49     os << "\n    in call to " << jni_function_name;
50   }
51   // TODO: is this useful given that we're about to dump the calling thread's stack?
52   if (current_method != NULL) {
53     os << "\n    from " << PrettyMethod(current_method);
54   }
55   os << "\n";
56   self->Dump(os);
57 
58   JavaVMExt* vm = Runtime::Current()->GetJavaVM();
59   if (vm->check_jni_abort_hook != NULL) {
60     vm->check_jni_abort_hook(vm->check_jni_abort_hook_data, os.str());
61   } else {
62     // Ensure that we get a native stack trace for this thread.
63     self->TransitionFromRunnableToSuspended(kNative);
64     LOG(FATAL) << os.str();
65     self->TransitionFromSuspendedToRunnable();  // Unreachable, keep annotalysis happy.
66   }
67 }
68 
JniAbortV(const char * jni_function_name,const char * fmt,va_list ap)69 static void JniAbortV(const char* jni_function_name, const char* fmt, va_list ap) {
70   std::string msg;
71   StringAppendV(&msg, fmt, ap);
72   JniAbort(jni_function_name, msg.c_str());
73 }
74 
JniAbortF(const char * jni_function_name,const char * fmt,...)75 void JniAbortF(const char* jni_function_name, const char* fmt, ...) {
76   va_list args;
77   va_start(args, fmt);
78   JniAbortV(jni_function_name, fmt, args);
79   va_end(args);
80 }
81 
82 /*
83  * ===========================================================================
84  *      JNI function helpers
85  * ===========================================================================
86  */
87 
IsSirtLocalRef(JNIEnv * env,jobject localRef)88 static bool IsSirtLocalRef(JNIEnv* env, jobject localRef) {
89   return GetIndirectRefKind(localRef) == kSirtOrInvalid &&
90       reinterpret_cast<JNIEnvExt*>(env)->self->SirtContains(localRef);
91 }
92 
93 // Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
94 // The code deliberately uses an invalid sequence of operations, so we
95 // need to pass it through unmodified.  Review that code before making
96 // any changes here.
97 #define kNoCopyMagic    0xd5aab57f
98 
99 // Flags passed into ScopedCheck.
100 #define kFlag_Default       0x0000
101 
102 #define kFlag_CritBad       0x0000      // Calling while in critical is not allowed.
103 #define kFlag_CritOkay      0x0001      // Calling while in critical is allowed.
104 #define kFlag_CritGet       0x0002      // This is a critical "get".
105 #define kFlag_CritRelease   0x0003      // This is a critical "release".
106 #define kFlag_CritMask      0x0003      // Bit mask to get "crit" value.
107 
108 #define kFlag_ExcepBad      0x0000      // Raised exceptions are not allowed.
109 #define kFlag_ExcepOkay     0x0004      // Raised exceptions are allowed.
110 
111 #define kFlag_Release       0x0010      // Are we in a non-critical release function?
112 #define kFlag_NullableUtf   0x0020      // Are our UTF parameters nullable?
113 
114 #define kFlag_Invocation    0x8000      // Part of the invocation interface (JavaVM*).
115 
116 #define kFlag_ForceTrace    0x80000000  // Add this to a JNI function's flags if you want to trace every call.
117 
118 static const char* gBuiltInPrefixes[] = {
119   "Landroid/",
120   "Lcom/android/",
121   "Lcom/google/android/",
122   "Ldalvik/",
123   "Ljava/",
124   "Ljavax/",
125   "Llibcore/",
126   "Lorg/apache/harmony/",
127   NULL
128 };
129 
ShouldTrace(JavaVMExt * vm,const mirror::ArtMethod * method)130 static bool ShouldTrace(JavaVMExt* vm, const mirror::ArtMethod* method)
131     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
132   // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
133   // when a native method that matches the -Xjnitrace argument calls a JNI function
134   // such as NewByteArray.
135   // If -verbose:third-party-jni is on, we want to log any JNI function calls
136   // made by a third-party native method.
137   std::string class_name(MethodHelper(method).GetDeclaringClassDescriptor());
138   if (!vm->trace.empty() && class_name.find(vm->trace) != std::string::npos) {
139     return true;
140   }
141   if (VLOG_IS_ON(third_party_jni)) {
142     // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
143     // like part of Android.
144     for (size_t i = 0; gBuiltInPrefixes[i] != NULL; ++i) {
145       if (StartsWith(class_name, gBuiltInPrefixes[i])) {
146         return false;
147       }
148     }
149     return true;
150   }
151   return false;
152 }
153 
154 class ScopedCheck {
155  public:
156   // For JNIEnv* functions.
ScopedCheck(JNIEnv * env,int flags,const char * functionName)157   explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName)
158       SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
159       : soa_(env) {
160     Init(flags, functionName, true);
161     CheckThread(flags);
162   }
163 
164   // For JavaVM* functions.
165   // TODO: it's not correct that this is a lock function, but making it so aids annotalysis.
ScopedCheck(JavaVM * vm,bool has_method,const char * functionName)166   explicit ScopedCheck(JavaVM* vm, bool has_method, const char* functionName)
167       SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
168       : soa_(vm) {
169     Init(kFlag_Invocation, functionName, has_method);
170   }
171 
UNLOCK_FUNCTION(Locks::mutator_lock_)172   ~ScopedCheck() UNLOCK_FUNCTION(Locks::mutator_lock_) {}
173 
soa()174   const ScopedObjectAccess& soa() {
175     return soa_;
176   }
177 
ForceCopy()178   bool ForceCopy() {
179     return Runtime::Current()->GetJavaVM()->force_copy;
180   }
181 
182   // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
183   // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
184   // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
185   // circumstances, but this is incorrect.
CheckClassName(const char * class_name)186   void CheckClassName(const char* class_name) {
187     if (!IsValidJniClassName(class_name)) {
188       JniAbortF(function_name_,
189                 "illegal class name '%s'\n"
190                 "    (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
191                 class_name);
192     }
193   }
194 
195   /*
196    * Verify that the field is of the appropriate type.  If the field has an
197    * object type, "java_object" is the object we're trying to assign into it.
198    *
199    * Works for both static and instance fields.
200    */
CheckFieldType(jobject java_object,jfieldID fid,char prim,bool isStatic)201   void CheckFieldType(jobject java_object, jfieldID fid, char prim, bool isStatic)
202       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
203     mirror::ArtField* f = CheckFieldID(fid);
204     if (f == NULL) {
205       return;
206     }
207     mirror::Class* field_type = FieldHelper(f).GetType();
208     if (!field_type->IsPrimitive()) {
209       if (java_object != NULL) {
210         mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
211         // If java_object is a weak global ref whose referent has been cleared,
212         // obj will be NULL.  Otherwise, obj should always be non-NULL
213         // and valid.
214         if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
215           Runtime::Current()->GetHeap()->DumpSpaces();
216           JniAbortF(function_name_, "field operation on invalid %s: %p",
217                     ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
218           return;
219         } else {
220           if (!obj->InstanceOf(field_type)) {
221             JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %s",
222                       PrettyField(f).c_str(), PrettyTypeOf(obj).c_str());
223             return;
224           }
225         }
226       }
227     } else if (field_type != Runtime::Current()->GetClassLinker()->FindPrimitiveClass(prim)) {
228       JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %c",
229                 PrettyField(f).c_str(), prim);
230       return;
231     }
232 
233     if (isStatic != f->IsStatic()) {
234       if (isStatic) {
235         JniAbortF(function_name_, "accessing non-static field %s as static", PrettyField(f).c_str());
236       } else {
237         JniAbortF(function_name_, "accessing static field %s as non-static", PrettyField(f).c_str());
238       }
239       return;
240     }
241   }
242 
243   /*
244    * Verify that this instance field ID is valid for this object.
245    *
246    * Assumes "jobj" has already been validated.
247    */
CheckInstanceFieldID(jobject java_object,jfieldID fid)248   void CheckInstanceFieldID(jobject java_object, jfieldID fid)
249       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
250     mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
251     if (o == NULL || !Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
252       Runtime::Current()->GetHeap()->DumpSpaces();
253       JniAbortF(function_name_, "field operation on invalid %s: %p",
254                 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
255       return;
256     }
257 
258     mirror::ArtField* f = CheckFieldID(fid);
259     if (f == NULL) {
260       return;
261     }
262     mirror::Class* c = o->GetClass();
263     FieldHelper fh(f);
264     if (c->FindInstanceField(fh.GetName(), fh.GetTypeDescriptor()) == NULL) {
265       JniAbortF(function_name_, "jfieldID %s not valid for an object of class %s",
266                 PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
267     }
268   }
269 
270   /*
271    * Verify that the pointer value is non-NULL.
272    */
CheckNonNull(const void * ptr)273   void CheckNonNull(const void* ptr) {
274     if (ptr == NULL) {
275       JniAbortF(function_name_, "non-nullable argument was NULL");
276     }
277   }
278 
279   /*
280    * Verify that the method's return type matches the type of call.
281    * 'expectedType' will be "L" for all objects, including arrays.
282    */
CheckSig(jmethodID mid,const char * expectedType,bool isStatic)283   void CheckSig(jmethodID mid, const char* expectedType, bool isStatic)
284       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
285     mirror::ArtMethod* m = CheckMethodID(mid);
286     if (m == NULL) {
287       return;
288     }
289     if (*expectedType != MethodHelper(m).GetShorty()[0]) {
290       JniAbortF(function_name_, "the return type of %s does not match %s",
291                 function_name_, PrettyMethod(m).c_str());
292     }
293     if (isStatic != m->IsStatic()) {
294       if (isStatic) {
295         JniAbortF(function_name_, "calling non-static method %s with %s",
296                   PrettyMethod(m).c_str(), function_name_);
297       } else {
298         JniAbortF(function_name_, "calling static method %s with %s",
299                   PrettyMethod(m).c_str(), function_name_);
300       }
301     }
302   }
303 
304   /*
305    * Verify that this static field ID is valid for this class.
306    *
307    * Assumes "java_class" has already been validated.
308    */
CheckStaticFieldID(jclass java_class,jfieldID fid)309   void CheckStaticFieldID(jclass java_class, jfieldID fid)
310       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
311     mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
312     const mirror::ArtField* f = CheckFieldID(fid);
313     if (f == NULL) {
314       return;
315     }
316     if (f->GetDeclaringClass() != c) {
317       JniAbortF(function_name_, "static jfieldID %p not valid for class %s",
318                 fid, PrettyClass(c).c_str());
319     }
320   }
321 
322   /*
323    * Verify that "mid" is appropriate for "java_class".
324    *
325    * A mismatch isn't dangerous, because the jmethodID defines the class.  In
326    * fact, java_class is unused in the implementation.  It's best if we don't
327    * allow bad code in the system though.
328    *
329    * Instances of "java_class" must be instances of the method's declaring class.
330    */
CheckStaticMethod(jclass java_class,jmethodID mid)331   void CheckStaticMethod(jclass java_class, jmethodID mid)
332       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
333     const mirror::ArtMethod* m = CheckMethodID(mid);
334     if (m == NULL) {
335       return;
336     }
337     mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
338     if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
339       JniAbortF(function_name_, "can't call static %s on class %s",
340                 PrettyMethod(m).c_str(), PrettyClass(c).c_str());
341     }
342   }
343 
344   /*
345    * Verify that "mid" is appropriate for "jobj".
346    *
347    * Make sure the object is an instance of the method's declaring class.
348    * (Note the mid might point to a declaration in an interface; this
349    * will be handled automatically by the instanceof check.)
350    */
CheckVirtualMethod(jobject java_object,jmethodID mid)351   void CheckVirtualMethod(jobject java_object, jmethodID mid)
352       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
353     const mirror::ArtMethod* m = CheckMethodID(mid);
354     if (m == NULL) {
355       return;
356     }
357     mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
358     if (!o->InstanceOf(m->GetDeclaringClass())) {
359       JniAbortF(function_name_, "can't call %s on instance of %s",
360                 PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
361     }
362   }
363 
364   /**
365    * The format string is a sequence of the following characters,
366    * and must be followed by arguments of the corresponding types
367    * in the same order.
368    *
369    * Java primitive types:
370    * B - jbyte
371    * C - jchar
372    * D - jdouble
373    * F - jfloat
374    * I - jint
375    * J - jlong
376    * S - jshort
377    * Z - jboolean (shown as true and false)
378    * V - void
379    *
380    * Java reference types:
381    * L - jobject
382    * a - jarray
383    * c - jclass
384    * s - jstring
385    *
386    * JNI types:
387    * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
388    * f - jfieldID
389    * m - jmethodID
390    * p - void*
391    * r - jint (for release mode arguments)
392    * u - const char* (Modified UTF-8)
393    * z - jsize (for lengths; use i if negative values are okay)
394    * v - JavaVM*
395    * E - JNIEnv*
396    * . - no argument; just print "..." (used for varargs JNI calls)
397    *
398    * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
399    */
Check(bool entry,const char * fmt0,...)400   void Check(bool entry, const char* fmt0, ...) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
401     va_list ap;
402 
403     const mirror::ArtMethod* traceMethod = NULL;
404     if (has_method_ && (!soa_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni))) {
405       // We need to guard some of the invocation interface's calls: a bad caller might
406       // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
407       Thread* self = Thread::Current();
408       if ((flags_ & kFlag_Invocation) == 0 || self != NULL) {
409         traceMethod = self->GetCurrentMethod(NULL);
410       }
411     }
412 
413     if (((flags_ & kFlag_ForceTrace) != 0) || (traceMethod != NULL && ShouldTrace(soa_.Vm(), traceMethod))) {
414       va_start(ap, fmt0);
415       std::string msg;
416       for (const char* fmt = fmt0; *fmt;) {
417         char ch = *fmt++;
418         if (ch == 'B') {  // jbyte
419           jbyte b = va_arg(ap, int);
420           if (b >= 0 && b < 10) {
421             StringAppendF(&msg, "%d", b);
422           } else {
423             StringAppendF(&msg, "%#x (%d)", b, b);
424           }
425         } else if (ch == 'C') {  // jchar
426           jchar c = va_arg(ap, int);
427           if (c < 0x7f && c >= ' ') {
428             StringAppendF(&msg, "U+%x ('%c')", c, c);
429           } else {
430             StringAppendF(&msg, "U+%x", c);
431           }
432         } else if (ch == 'F' || ch == 'D') {  // jfloat, jdouble
433           StringAppendF(&msg, "%g", va_arg(ap, double));
434         } else if (ch == 'I' || ch == 'S') {  // jint, jshort
435           StringAppendF(&msg, "%d", va_arg(ap, int));
436         } else if (ch == 'J') {  // jlong
437           StringAppendF(&msg, "%lld", va_arg(ap, jlong));
438         } else if (ch == 'Z') {  // jboolean
439           StringAppendF(&msg, "%s", va_arg(ap, int) ? "true" : "false");
440         } else if (ch == 'V') {  // void
441           msg += "void";
442         } else if (ch == 'v') {  // JavaVM*
443           JavaVM* vm = va_arg(ap, JavaVM*);
444           StringAppendF(&msg, "(JavaVM*)%p", vm);
445         } else if (ch == 'E') {  // JNIEnv*
446           JNIEnv* env = va_arg(ap, JNIEnv*);
447           StringAppendF(&msg, "(JNIEnv*)%p", env);
448         } else if (ch == 'L' || ch == 'a' || ch == 's') {  // jobject, jarray, jstring
449           // For logging purposes, these are identical.
450           jobject o = va_arg(ap, jobject);
451           if (o == NULL) {
452             msg += "NULL";
453           } else {
454             StringAppendF(&msg, "%p", o);
455           }
456         } else if (ch == 'b') {  // jboolean (JNI-style)
457           jboolean b = va_arg(ap, int);
458           msg += (b ? "JNI_TRUE" : "JNI_FALSE");
459         } else if (ch == 'c') {  // jclass
460           jclass jc = va_arg(ap, jclass);
461           mirror::Class* c = reinterpret_cast<mirror::Class*>(Thread::Current()->DecodeJObject(jc));
462           if (c == NULL) {
463             msg += "NULL";
464           } else if (c == kInvalidIndirectRefObject || !Runtime::Current()->GetHeap()->IsHeapAddress(c)) {
465             StringAppendF(&msg, "INVALID POINTER:%p", jc);
466           } else if (!c->IsClass()) {
467             msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
468           } else {
469             msg += PrettyClass(c);
470             if (!entry) {
471               StringAppendF(&msg, " (%p)", jc);
472             }
473           }
474         } else if (ch == 'f') {  // jfieldID
475           jfieldID fid = va_arg(ap, jfieldID);
476           mirror::ArtField* f = reinterpret_cast<mirror::ArtField*>(fid);
477           msg += PrettyField(f);
478           if (!entry) {
479             StringAppendF(&msg, " (%p)", fid);
480           }
481         } else if (ch == 'z') {  // non-negative jsize
482           // You might expect jsize to be size_t, but it's not; it's the same as jint.
483           // We only treat this specially so we can do the non-negative check.
484           // TODO: maybe this wasn't worth it?
485           jint i = va_arg(ap, jint);
486           StringAppendF(&msg, "%d", i);
487         } else if (ch == 'm') {  // jmethodID
488           jmethodID mid = va_arg(ap, jmethodID);
489           mirror::ArtMethod* m = reinterpret_cast<mirror::ArtMethod*>(mid);
490           msg += PrettyMethod(m);
491           if (!entry) {
492             StringAppendF(&msg, " (%p)", mid);
493           }
494         } else if (ch == 'p') {  // void* ("pointer")
495           void* p = va_arg(ap, void*);
496           if (p == NULL) {
497             msg += "NULL";
498           } else {
499             StringAppendF(&msg, "(void*) %p", p);
500           }
501         } else if (ch == 'r') {  // jint (release mode)
502           jint releaseMode = va_arg(ap, jint);
503           if (releaseMode == 0) {
504             msg += "0";
505           } else if (releaseMode == JNI_ABORT) {
506             msg += "JNI_ABORT";
507           } else if (releaseMode == JNI_COMMIT) {
508             msg += "JNI_COMMIT";
509           } else {
510             StringAppendF(&msg, "invalid release mode %d", releaseMode);
511           }
512         } else if (ch == 'u') {  // const char* (Modified UTF-8)
513           const char* utf = va_arg(ap, const char*);
514           if (utf == NULL) {
515             msg += "NULL";
516           } else {
517             StringAppendF(&msg, "\"%s\"", utf);
518           }
519         } else if (ch == '.') {
520           msg += "...";
521         } else {
522           JniAbortF(function_name_, "unknown trace format specifier: %c", ch);
523           return;
524         }
525         if (*fmt) {
526           StringAppendF(&msg, ", ");
527         }
528       }
529       va_end(ap);
530 
531       if ((flags_ & kFlag_ForceTrace) != 0) {
532         LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
533       } else if (entry) {
534         if (has_method_) {
535           std::string methodName(PrettyMethod(traceMethod, false));
536           LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
537           indent_ = methodName.size() + 1;
538         } else {
539           LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
540           indent_ = 0;
541         }
542       } else {
543         LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
544       }
545     }
546 
547     // We always do the thorough checks on entry, and never on exit...
548     if (entry) {
549       va_start(ap, fmt0);
550       for (const char* fmt = fmt0; *fmt; ++fmt) {
551         char ch = *fmt;
552         if (ch == 'a') {
553           CheckArray(va_arg(ap, jarray));
554         } else if (ch == 'c') {
555           CheckInstance(kClass, va_arg(ap, jclass));
556         } else if (ch == 'L') {
557           CheckObject(va_arg(ap, jobject));
558         } else if (ch == 'r') {
559           CheckReleaseMode(va_arg(ap, jint));
560         } else if (ch == 's') {
561           CheckInstance(kString, va_arg(ap, jstring));
562         } else if (ch == 'u') {
563           if ((flags_ & kFlag_Release) != 0) {
564             CheckNonNull(va_arg(ap, const char*));
565           } else {
566             bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
567             CheckUtfString(va_arg(ap, const char*), nullable);
568           }
569         } else if (ch == 'z') {
570           CheckLengthPositive(va_arg(ap, jsize));
571         } else if (strchr("BCISZbfmpEv", ch) != NULL) {
572           va_arg(ap, uint32_t);  // Skip this argument.
573         } else if (ch == 'D' || ch == 'F') {
574           va_arg(ap, double);  // Skip this argument.
575         } else if (ch == 'J') {
576           va_arg(ap, uint64_t);  // Skip this argument.
577         } else if (ch == '.') {
578         } else {
579           LOG(FATAL) << "Unknown check format specifier: " << ch;
580         }
581       }
582       va_end(ap);
583     }
584   }
585 
586   enum InstanceKind {
587     kClass,
588     kDirectByteBuffer,
589     kObject,
590     kString,
591     kThrowable,
592   };
593 
594   /*
595    * Verify that "jobj" is a valid non-NULL object reference, and points to
596    * an instance of expectedClass.
597    *
598    * Because we're looking at an object on the GC heap, we have to switch
599    * to "running" mode before doing the checks.
600    */
CheckInstance(InstanceKind kind,jobject java_object)601   bool CheckInstance(InstanceKind kind, jobject java_object)
602       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
603     const char* what = NULL;
604     switch (kind) {
605     case kClass:
606       what = "jclass";
607       break;
608     case kDirectByteBuffer:
609       what = "direct ByteBuffer";
610       break;
611     case kObject:
612       what = "jobject";
613       break;
614     case kString:
615       what = "jstring";
616       break;
617     case kThrowable:
618       what = "jthrowable";
619       break;
620     default:
621       LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
622     }
623 
624     if (java_object == NULL) {
625       JniAbortF(function_name_, "%s received null %s", function_name_, what);
626       return false;
627     }
628 
629     mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
630     if (!Runtime::Current()->GetHeap()->IsHeapAddress(obj)) {
631       Runtime::Current()->GetHeap()->DumpSpaces();
632       JniAbortF(function_name_, "%s is an invalid %s: %p (%p)",
633                 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object, obj);
634       return false;
635     }
636 
637     bool okay = true;
638     switch (kind) {
639     case kClass:
640       okay = obj->IsClass();
641       break;
642     case kDirectByteBuffer:
643       UNIMPLEMENTED(FATAL);
644       break;
645     case kString:
646       okay = obj->GetClass()->IsStringClass();
647       break;
648     case kThrowable:
649       okay = obj->GetClass()->IsThrowableClass();
650       break;
651     case kObject:
652       break;
653     }
654     if (!okay) {
655       JniAbortF(function_name_, "%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
656       return false;
657     }
658 
659     return true;
660   }
661 
662  private:
663   // Set "has_method" to true if we have a valid thread with a method pointer.
664   // We won't have one before attaching a thread, after detaching a thread, or
665   // when shutting down the runtime.
Init(int flags,const char * functionName,bool has_method)666   void Init(int flags, const char* functionName, bool has_method) {
667     flags_ = flags;
668     function_name_ = functionName;
669     has_method_ = has_method;
670   }
671 
672   /*
673    * Verify that "array" is non-NULL and points to an Array object.
674    *
675    * Since we're dealing with objects, switch to "running" mode.
676    */
CheckArray(jarray java_array)677   void CheckArray(jarray java_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
678     if (java_array == NULL) {
679       JniAbortF(function_name_, "jarray was NULL");
680       return;
681     }
682 
683     mirror::Array* a = soa_.Decode<mirror::Array*>(java_array);
684     if (!Runtime::Current()->GetHeap()->IsHeapAddress(a)) {
685       Runtime::Current()->GetHeap()->DumpSpaces();
686       JniAbortF(function_name_, "jarray is an invalid %s: %p (%p)",
687                 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), java_array, a);
688     } else if (!a->IsArrayInstance()) {
689       JniAbortF(function_name_, "jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
690     }
691   }
692 
CheckLengthPositive(jsize length)693   void CheckLengthPositive(jsize length) {
694     if (length < 0) {
695       JniAbortF(function_name_, "negative jsize: %d", length);
696     }
697   }
698 
CheckFieldID(jfieldID fid)699   mirror::ArtField* CheckFieldID(jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
700     if (fid == NULL) {
701       JniAbortF(function_name_, "jfieldID was NULL");
702       return NULL;
703     }
704     mirror::ArtField* f = soa_.DecodeField(fid);
705     if (!Runtime::Current()->GetHeap()->IsHeapAddress(f) || !f->IsArtField()) {
706       Runtime::Current()->GetHeap()->DumpSpaces();
707       JniAbortF(function_name_, "invalid jfieldID: %p", fid);
708       return NULL;
709     }
710     return f;
711   }
712 
CheckMethodID(jmethodID mid)713   mirror::ArtMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
714     if (mid == NULL) {
715       JniAbortF(function_name_, "jmethodID was NULL");
716       return NULL;
717     }
718     mirror::ArtMethod* m = soa_.DecodeMethod(mid);
719     if (!Runtime::Current()->GetHeap()->IsHeapAddress(m) || !m->IsArtMethod()) {
720       Runtime::Current()->GetHeap()->DumpSpaces();
721       JniAbortF(function_name_, "invalid jmethodID: %p", mid);
722       return NULL;
723     }
724     return m;
725   }
726 
727   /*
728    * Verify that "jobj" is a valid object, and that it's an object that JNI
729    * is allowed to know about.  We allow NULL references.
730    *
731    * Switches to "running" mode before performing checks.
732    */
CheckObject(jobject java_object)733   void CheckObject(jobject java_object)
734       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
735     if (java_object == NULL) {
736       return;
737     }
738 
739     mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
740     if (!Runtime::Current()->GetHeap()->IsHeapAddress(o)) {
741       Runtime::Current()->GetHeap()->DumpSpaces();
742       // TODO: when we remove work_around_app_jni_bugs, this should be impossible.
743       JniAbortF(function_name_, "native code passing in reference to invalid %s: %p",
744                 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
745     }
746   }
747 
748   /*
749    * Verify that the "mode" argument passed to a primitive array Release
750    * function is one of the valid values.
751    */
CheckReleaseMode(jint mode)752   void CheckReleaseMode(jint mode) {
753     if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
754       JniAbortF(function_name_, "unknown value for release mode: %d", mode);
755     }
756   }
757 
CheckThread(int flags)758   void CheckThread(int flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
759     Thread* self = Thread::Current();
760     if (self == NULL) {
761       JniAbortF(function_name_, "a thread (tid %d) is making JNI calls without being attached", GetTid());
762       return;
763     }
764 
765     // Get the *correct* JNIEnv by going through our TLS pointer.
766     JNIEnvExt* threadEnv = self->GetJniEnv();
767 
768     // Verify that the current thread is (a) attached and (b) associated with
769     // this particular instance of JNIEnv.
770     if (soa_.Env() != threadEnv) {
771       if (soa_.Vm()->work_around_app_jni_bugs) {
772         // If we're keeping broken code limping along, we need to suppress the abort...
773         LOG(ERROR) << "APP BUG DETECTED: thread " << *self << " using JNIEnv* from thread " << *soa_.Self();
774       } else {
775         JniAbortF(function_name_, "thread %s using JNIEnv* from thread %s",
776                   ToStr<Thread>(*self).c_str(), ToStr<Thread>(*soa_.Self()).c_str());
777         return;
778       }
779     }
780 
781     // Verify that, if this thread previously made a critical "get" call, we
782     // do the corresponding "release" call before we try anything else.
783     switch (flags & kFlag_CritMask) {
784     case kFlag_CritOkay:    // okay to call this method
785       break;
786     case kFlag_CritBad:     // not okay to call
787       if (threadEnv->critical) {
788         JniAbortF(function_name_, "thread %s using JNI after critical get", ToStr<Thread>(*self).c_str());
789         return;
790       }
791       break;
792     case kFlag_CritGet:     // this is a "get" call
793       // Don't check here; we allow nested gets.
794       threadEnv->critical++;
795       break;
796     case kFlag_CritRelease:  // this is a "release" call
797       threadEnv->critical--;
798       if (threadEnv->critical < 0) {
799         JniAbortF(function_name_, "thread %s called too many critical releases", ToStr<Thread>(*self).c_str());
800         return;
801       }
802       break;
803     default:
804       LOG(FATAL) << "Bad flags (internal error): " << flags;
805     }
806 
807     // Verify that, if an exception has been raised, the native code doesn't
808     // make any JNI calls other than the Exception* methods.
809     if ((flags & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
810       ThrowLocation throw_location;
811       mirror::Throwable* exception = self->GetException(&throw_location);
812       std::string type(PrettyTypeOf(exception));
813       JniAbortF(function_name_, "JNI %s called with pending exception '%s' thrown in %s",
814                 function_name_, type.c_str(), throw_location.Dump().c_str());
815       return;
816     }
817   }
818 
819   // Verifies that "bytes" points to valid Modified UTF-8 data.
CheckUtfString(const char * bytes,bool nullable)820   void CheckUtfString(const char* bytes, bool nullable) {
821     if (bytes == NULL) {
822       if (!nullable) {
823         JniAbortF(function_name_, "non-nullable const char* was NULL");
824         return;
825       }
826       return;
827     }
828 
829     const char* errorKind = NULL;
830     uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
831     if (errorKind != NULL) {
832       JniAbortF(function_name_,
833                 "input is not valid Modified UTF-8: illegal %s byte %#x\n"
834                 "    string: '%s'", errorKind, utf8, bytes);
835       return;
836     }
837   }
838 
CheckUtfBytes(const char * bytes,const char ** errorKind)839   static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
840     while (*bytes != '\0') {
841       uint8_t utf8 = *(bytes++);
842       // Switch on the high four bits.
843       switch (utf8 >> 4) {
844       case 0x00:
845       case 0x01:
846       case 0x02:
847       case 0x03:
848       case 0x04:
849       case 0x05:
850       case 0x06:
851       case 0x07:
852         // Bit pattern 0xxx. No need for any extra bytes.
853         break;
854       case 0x08:
855       case 0x09:
856       case 0x0a:
857       case 0x0b:
858       case 0x0f:
859         /*
860          * Bit pattern 10xx or 1111, which are illegal start bytes.
861          * Note: 1111 is valid for normal UTF-8, but not the
862          * Modified UTF-8 used here.
863          */
864         *errorKind = "start";
865         return utf8;
866       case 0x0e:
867         // Bit pattern 1110, so there are two additional bytes.
868         utf8 = *(bytes++);
869         if ((utf8 & 0xc0) != 0x80) {
870           *errorKind = "continuation";
871           return utf8;
872         }
873         // Fall through to take care of the final byte.
874       case 0x0c:
875       case 0x0d:
876         // Bit pattern 110x, so there is one additional byte.
877         utf8 = *(bytes++);
878         if ((utf8 & 0xc0) != 0x80) {
879           *errorKind = "continuation";
880           return utf8;
881         }
882         break;
883       }
884     }
885     return 0;
886   }
887 
888   const ScopedObjectAccess soa_;
889   const char* function_name_;
890   int flags_;
891   bool has_method_;
892   int indent_;
893 
894   DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
895 };
896 
897 #define CHECK_JNI_ENTRY(flags, types, args...) \
898   ScopedCheck sc(env, flags, __FUNCTION__); \
899   sc.Check(true, types, ##args)
900 
901 #define CHECK_JNI_EXIT(type, exp) ({ \
902     auto _rc = (exp); \
903   sc.Check(false, type, _rc); \
904   _rc; })
905 #define CHECK_JNI_EXIT_VOID() \
906   sc.Check(false, "V")
907 
908 /*
909  * ===========================================================================
910  *      Guarded arrays
911  * ===========================================================================
912  */
913 
914 #define kGuardLen       512         /* must be multiple of 2 */
915 #define kGuardPattern   0xd5e3      /* uncommon values; d5e3d5e3 invalid addr */
916 #define kGuardMagic     0xffd5aa96
917 
918 /* this gets tucked in at the start of the buffer; struct size must be even */
919 struct GuardedCopy {
920   uint32_t magic;
921   uLong adler;
922   size_t original_length;
923   const void* original_ptr;
924 
925   /* find the GuardedCopy given the pointer into the "live" data */
FromDataart::GuardedCopy926   static inline const GuardedCopy* FromData(const void* dataBuf) {
927     return reinterpret_cast<const GuardedCopy*>(ActualBuffer(dataBuf));
928   }
929 
930   /*
931    * Create an over-sized buffer to hold the contents of "buf".  Copy it in,
932    * filling in the area around it with guard data.
933    *
934    * We use a 16-bit pattern to make a rogue memset less likely to elude us.
935    */
Createart::GuardedCopy936   static void* Create(const void* buf, size_t len, bool modOkay) {
937     size_t newLen = ActualLength(len);
938     uint8_t* newBuf = DebugAlloc(newLen);
939 
940     // Fill it in with a pattern.
941     uint16_t* pat = reinterpret_cast<uint16_t*>(newBuf);
942     for (size_t i = 0; i < newLen / 2; i++) {
943       *pat++ = kGuardPattern;
944     }
945 
946     // Copy the data in; note "len" could be zero.
947     memcpy(newBuf + kGuardLen / 2, buf, len);
948 
949     // If modification is not expected, grab a checksum.
950     uLong adler = 0;
951     if (!modOkay) {
952       adler = adler32(0L, Z_NULL, 0);
953       adler = adler32(adler, reinterpret_cast<const Bytef*>(buf), len);
954       *reinterpret_cast<uLong*>(newBuf) = adler;
955     }
956 
957     GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf);
958     pExtra->magic = kGuardMagic;
959     pExtra->adler = adler;
960     pExtra->original_ptr = buf;
961     pExtra->original_length = len;
962 
963     return newBuf + kGuardLen / 2;
964   }
965 
966   /*
967    * Free up the guard buffer, scrub it, and return the original pointer.
968    */
Destroyart::GuardedCopy969   static void* Destroy(void* dataBuf) {
970     const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
971     void* original_ptr = const_cast<void*>(pExtra->original_ptr);
972     size_t len = pExtra->original_length;
973     DebugFree(dataBuf, len);
974     return original_ptr;
975   }
976 
977   /*
978    * Verify the guard area and, if "modOkay" is false, that the data itself
979    * has not been altered.
980    *
981    * The caller has already checked that "dataBuf" is non-NULL.
982    */
Checkart::GuardedCopy983   static void Check(const char* functionName, const void* dataBuf, bool modOkay) {
984     static const uint32_t kMagicCmp = kGuardMagic;
985     const uint8_t* fullBuf = ActualBuffer(dataBuf);
986     const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
987 
988     // Before we do anything with "pExtra", check the magic number.  We
989     // do the check with memcmp rather than "==" in case the pointer is
990     // unaligned.  If it points to completely bogus memory we're going
991     // to crash, but there's no easy way around that.
992     if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
993       uint8_t buf[4];
994       memcpy(buf, &pExtra->magic, 4);
995       JniAbortF(functionName,
996           "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
997           buf[3], buf[2], buf[1], buf[0], dataBuf);  // Assumes little-endian.
998     }
999 
1000     size_t len = pExtra->original_length;
1001 
1002     // Check bottom half of guard; skip over optional checksum storage.
1003     const uint16_t* pat = reinterpret_cast<const uint16_t*>(fullBuf);
1004     for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
1005       if (pat[i] != kGuardPattern) {
1006         JniAbortF(functionName, "guard pattern(1) disturbed at %p +%d", fullBuf, i*2);
1007       }
1008     }
1009 
1010     int offset = kGuardLen / 2 + len;
1011     if (offset & 0x01) {
1012       // Odd byte; expected value depends on endian.
1013       const uint16_t patSample = kGuardPattern;
1014       uint8_t expected_byte = reinterpret_cast<const uint8_t*>(&patSample)[1];
1015       if (fullBuf[offset] != expected_byte) {
1016         JniAbortF(functionName, "guard pattern disturbed in odd byte after %p +%d 0x%02x 0x%02x",
1017                   fullBuf, offset, fullBuf[offset], expected_byte);
1018       }
1019       offset++;
1020     }
1021 
1022     // Check top half of guard.
1023     pat = reinterpret_cast<const uint16_t*>(fullBuf + offset);
1024     for (size_t i = 0; i < kGuardLen / 4; i++) {
1025       if (pat[i] != kGuardPattern) {
1026         JniAbortF(functionName, "guard pattern(2) disturbed at %p +%d", fullBuf, offset + i*2);
1027       }
1028     }
1029 
1030     // If modification is not expected, verify checksum.  Strictly speaking
1031     // this is wrong: if we told the client that we made a copy, there's no
1032     // reason they can't alter the buffer.
1033     if (!modOkay) {
1034       uLong adler = adler32(0L, Z_NULL, 0);
1035       adler = adler32(adler, (const Bytef*)dataBuf, len);
1036       if (pExtra->adler != adler) {
1037         JniAbortF(functionName, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1038                   pExtra->adler, adler, dataBuf);
1039       }
1040     }
1041   }
1042 
1043  private:
DebugAllocart::GuardedCopy1044   static uint8_t* DebugAlloc(size_t len) {
1045     void* result = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1046     if (result == MAP_FAILED) {
1047       PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1048     }
1049     return reinterpret_cast<uint8_t*>(result);
1050   }
1051 
DebugFreeart::GuardedCopy1052   static void DebugFree(void* dataBuf, size_t len) {
1053     uint8_t* fullBuf = ActualBuffer(dataBuf);
1054     size_t totalByteCount = ActualLength(len);
1055     // TODO: we could mprotect instead, and keep the allocation around for a while.
1056     // This would be even more expensive, but it might catch more errors.
1057     // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) {
1058     //     PLOG(WARNING) << "mprotect(PROT_NONE) failed";
1059     // }
1060     if (munmap(fullBuf, totalByteCount) != 0) {
1061       PLOG(FATAL) << "munmap(" << reinterpret_cast<void*>(fullBuf) << ", " << totalByteCount << ") failed";
1062     }
1063   }
1064 
ActualBufferart::GuardedCopy1065   static const uint8_t* ActualBuffer(const void* dataBuf) {
1066     return reinterpret_cast<const uint8_t*>(dataBuf) - kGuardLen / 2;
1067   }
1068 
ActualBufferart::GuardedCopy1069   static uint8_t* ActualBuffer(void* dataBuf) {
1070     return reinterpret_cast<uint8_t*>(dataBuf) - kGuardLen / 2;
1071   }
1072 
1073   // Underlying length of a user allocation of 'length' bytes.
ActualLengthart::GuardedCopy1074   static size_t ActualLength(size_t length) {
1075     return (length + kGuardLen + 1) & ~0x01;
1076   }
1077 };
1078 
1079 /*
1080  * Create a guarded copy of a primitive array.  Modifications to the copied
1081  * data are allowed.  Returns a pointer to the copied data.
1082  */
CreateGuardedPACopy(JNIEnv * env,const jarray java_array,jboolean * isCopy)1083 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* isCopy) {
1084   ScopedObjectAccess soa(env);
1085 
1086   mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1087   size_t component_size = a->GetClass()->GetComponentSize();
1088   size_t byte_count = a->GetLength() * component_size;
1089   void* result = GuardedCopy::Create(a->GetRawData(component_size), byte_count, true);
1090   if (isCopy != NULL) {
1091     *isCopy = JNI_TRUE;
1092   }
1093   return result;
1094 }
1095 
1096 /*
1097  * Perform the array "release" operation, which may or may not copy data
1098  * back into the managed heap, and may or may not release the underlying storage.
1099  */
ReleaseGuardedPACopy(JNIEnv * env,jarray java_array,void * dataBuf,int mode)1100 static void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf, int mode) {
1101   if (reinterpret_cast<uintptr_t>(dataBuf) == kNoCopyMagic) {
1102     return;
1103   }
1104 
1105   ScopedObjectAccess soa(env);
1106   mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1107 
1108   GuardedCopy::Check(__FUNCTION__, dataBuf, true);
1109 
1110   if (mode != JNI_ABORT) {
1111     size_t len = GuardedCopy::FromData(dataBuf)->original_length;
1112     memcpy(a->GetRawData(a->GetClass()->GetComponentSize()), dataBuf, len);
1113   }
1114   if (mode != JNI_COMMIT) {
1115     GuardedCopy::Destroy(dataBuf);
1116   }
1117 }
1118 
1119 /*
1120  * ===========================================================================
1121  *      JNI functions
1122  * ===========================================================================
1123  */
1124 
1125 class CheckJNI {
1126  public:
GetVersion(JNIEnv * env)1127   static jint GetVersion(JNIEnv* env) {
1128     CHECK_JNI_ENTRY(kFlag_Default, "E", env);
1129     return CHECK_JNI_EXIT("I", baseEnv(env)->GetVersion(env));
1130   }
1131 
DefineClass(JNIEnv * env,const char * name,jobject loader,const jbyte * buf,jsize bufLen)1132   static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, jsize bufLen) {
1133     CHECK_JNI_ENTRY(kFlag_Default, "EuLpz", env, name, loader, buf, bufLen);
1134     sc.CheckClassName(name);
1135     return CHECK_JNI_EXIT("c", baseEnv(env)->DefineClass(env, name, loader, buf, bufLen));
1136   }
1137 
FindClass(JNIEnv * env,const char * name)1138   static jclass FindClass(JNIEnv* env, const char* name) {
1139     CHECK_JNI_ENTRY(kFlag_Default, "Eu", env, name);
1140     sc.CheckClassName(name);
1141     return CHECK_JNI_EXIT("c", baseEnv(env)->FindClass(env, name));
1142   }
1143 
GetSuperclass(JNIEnv * env,jclass c)1144   static jclass GetSuperclass(JNIEnv* env, jclass c) {
1145     CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1146     return CHECK_JNI_EXIT("c", baseEnv(env)->GetSuperclass(env, c));
1147   }
1148 
IsAssignableFrom(JNIEnv * env,jclass c1,jclass c2)1149   static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
1150     CHECK_JNI_ENTRY(kFlag_Default, "Ecc", env, c1, c2);
1151     return CHECK_JNI_EXIT("b", baseEnv(env)->IsAssignableFrom(env, c1, c2));
1152   }
1153 
FromReflectedMethod(JNIEnv * env,jobject method)1154   static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1155     CHECK_JNI_ENTRY(kFlag_Default, "EL", env, method);
1156     // TODO: check that 'field' is a java.lang.reflect.Method.
1157     return CHECK_JNI_EXIT("m", baseEnv(env)->FromReflectedMethod(env, method));
1158   }
1159 
FromReflectedField(JNIEnv * env,jobject field)1160   static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1161     CHECK_JNI_ENTRY(kFlag_Default, "EL", env, field);
1162     // TODO: check that 'field' is a java.lang.reflect.Field.
1163     return CHECK_JNI_EXIT("f", baseEnv(env)->FromReflectedField(env, field));
1164   }
1165 
ToReflectedMethod(JNIEnv * env,jclass cls,jmethodID mid,jboolean isStatic)1166   static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1167     CHECK_JNI_ENTRY(kFlag_Default, "Ecmb", env, cls, mid, isStatic);
1168     return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic));
1169   }
1170 
ToReflectedField(JNIEnv * env,jclass cls,jfieldID fid,jboolean isStatic)1171   static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1172     CHECK_JNI_ENTRY(kFlag_Default, "Ecfb", env, cls, fid, isStatic);
1173     return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedField(env, cls, fid, isStatic));
1174   }
1175 
Throw(JNIEnv * env,jthrowable obj)1176   static jint Throw(JNIEnv* env, jthrowable obj) {
1177     CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1178     // TODO: check that 'obj' is a java.lang.Throwable.
1179     return CHECK_JNI_EXIT("I", baseEnv(env)->Throw(env, obj));
1180   }
1181 
ThrowNew(JNIEnv * env,jclass c,const char * message)1182   static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
1183     CHECK_JNI_ENTRY(kFlag_NullableUtf, "Ecu", env, c, message);
1184     return CHECK_JNI_EXIT("I", baseEnv(env)->ThrowNew(env, c, message));
1185   }
1186 
ExceptionOccurred(JNIEnv * env)1187   static jthrowable ExceptionOccurred(JNIEnv* env) {
1188     CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1189     return CHECK_JNI_EXIT("L", baseEnv(env)->ExceptionOccurred(env));
1190   }
1191 
ExceptionDescribe(JNIEnv * env)1192   static void ExceptionDescribe(JNIEnv* env) {
1193     CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1194     baseEnv(env)->ExceptionDescribe(env);
1195     CHECK_JNI_EXIT_VOID();
1196   }
1197 
ExceptionClear(JNIEnv * env)1198   static void ExceptionClear(JNIEnv* env) {
1199     CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1200     baseEnv(env)->ExceptionClear(env);
1201     CHECK_JNI_EXIT_VOID();
1202   }
1203 
FatalError(JNIEnv * env,const char * msg)1204   static void FatalError(JNIEnv* env, const char* msg) {
1205     // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1206     // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1207     // and it's not unimaginable that you don't know that you do. So we allow it.
1208     CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_NullableUtf, "Eu", env, msg);
1209     baseEnv(env)->FatalError(env, msg);
1210     CHECK_JNI_EXIT_VOID();
1211   }
1212 
PushLocalFrame(JNIEnv * env,jint capacity)1213   static jint PushLocalFrame(JNIEnv* env, jint capacity) {
1214     CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EI", env, capacity);
1215     return CHECK_JNI_EXIT("I", baseEnv(env)->PushLocalFrame(env, capacity));
1216   }
1217 
PopLocalFrame(JNIEnv * env,jobject res)1218   static jobject PopLocalFrame(JNIEnv* env, jobject res) {
1219     CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, res);
1220     return CHECK_JNI_EXIT("L", baseEnv(env)->PopLocalFrame(env, res));
1221   }
1222 
NewGlobalRef(JNIEnv * env,jobject obj)1223   static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
1224     CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1225     return CHECK_JNI_EXIT("L", baseEnv(env)->NewGlobalRef(env, obj));
1226   }
1227 
NewLocalRef(JNIEnv * env,jobject ref)1228   static jobject NewLocalRef(JNIEnv* env, jobject ref) {
1229     CHECK_JNI_ENTRY(kFlag_Default, "EL", env, ref);
1230     return CHECK_JNI_EXIT("L", baseEnv(env)->NewLocalRef(env, ref));
1231   }
1232 
DeleteGlobalRef(JNIEnv * env,jobject globalRef)1233   static void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
1234     CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, globalRef);
1235     if (globalRef != NULL && GetIndirectRefKind(globalRef) != kGlobal) {
1236       JniAbortF(__FUNCTION__, "DeleteGlobalRef on %s: %p",
1237                 ToStr<IndirectRefKind>(GetIndirectRefKind(globalRef)).c_str(), globalRef);
1238     } else {
1239       baseEnv(env)->DeleteGlobalRef(env, globalRef);
1240       CHECK_JNI_EXIT_VOID();
1241     }
1242   }
1243 
DeleteWeakGlobalRef(JNIEnv * env,jweak weakGlobalRef)1244   static void DeleteWeakGlobalRef(JNIEnv* env, jweak weakGlobalRef) {
1245     CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, weakGlobalRef);
1246     if (weakGlobalRef != NULL && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
1247       JniAbortF(__FUNCTION__, "DeleteWeakGlobalRef on %s: %p",
1248                 ToStr<IndirectRefKind>(GetIndirectRefKind(weakGlobalRef)).c_str(), weakGlobalRef);
1249     } else {
1250       baseEnv(env)->DeleteWeakGlobalRef(env, weakGlobalRef);
1251       CHECK_JNI_EXIT_VOID();
1252     }
1253   }
1254 
DeleteLocalRef(JNIEnv * env,jobject localRef)1255   static void DeleteLocalRef(JNIEnv* env, jobject localRef) {
1256     CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, localRef);
1257     if (localRef != NULL && GetIndirectRefKind(localRef) != kLocal && !IsSirtLocalRef(env, localRef)) {
1258       JniAbortF(__FUNCTION__, "DeleteLocalRef on %s: %p",
1259                 ToStr<IndirectRefKind>(GetIndirectRefKind(localRef)).c_str(), localRef);
1260     } else {
1261       baseEnv(env)->DeleteLocalRef(env, localRef);
1262       CHECK_JNI_EXIT_VOID();
1263     }
1264   }
1265 
EnsureLocalCapacity(JNIEnv * env,jint capacity)1266   static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1267     CHECK_JNI_ENTRY(kFlag_Default, "EI", env, capacity);
1268     return CHECK_JNI_EXIT("I", baseEnv(env)->EnsureLocalCapacity(env, capacity));
1269   }
1270 
IsSameObject(JNIEnv * env,jobject ref1,jobject ref2)1271   static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1272     CHECK_JNI_ENTRY(kFlag_Default, "ELL", env, ref1, ref2);
1273     return CHECK_JNI_EXIT("b", baseEnv(env)->IsSameObject(env, ref1, ref2));
1274   }
1275 
AllocObject(JNIEnv * env,jclass c)1276   static jobject AllocObject(JNIEnv* env, jclass c) {
1277     CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1278     return CHECK_JNI_EXIT("L", baseEnv(env)->AllocObject(env, c));
1279   }
1280 
NewObject(JNIEnv * env,jclass c,jmethodID mid,...)1281   static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1282     CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1283     va_list args;
1284     va_start(args, mid);
1285     jobject result = baseEnv(env)->NewObjectV(env, c, mid, args);
1286     va_end(args);
1287     return CHECK_JNI_EXIT("L", result);
1288   }
1289 
NewObjectV(JNIEnv * env,jclass c,jmethodID mid,va_list args)1290   static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list args) {
1291     CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1292     return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectV(env, c, mid, args));
1293   }
1294 
NewObjectA(JNIEnv * env,jclass c,jmethodID mid,jvalue * args)1295   static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) {
1296     CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1297     return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectA(env, c, mid, args));
1298   }
1299 
GetObjectClass(JNIEnv * env,jobject obj)1300   static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1301     CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1302     return CHECK_JNI_EXIT("c", baseEnv(env)->GetObjectClass(env, obj));
1303   }
1304 
IsInstanceOf(JNIEnv * env,jobject obj,jclass c)1305   static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1306     CHECK_JNI_ENTRY(kFlag_Default, "ELc", env, obj, c);
1307     return CHECK_JNI_EXIT("b", baseEnv(env)->IsInstanceOf(env, obj, c));
1308   }
1309 
GetMethodID(JNIEnv * env,jclass c,const char * name,const char * sig)1310   static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1311     CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1312     return CHECK_JNI_EXIT("m", baseEnv(env)->GetMethodID(env, c, name, sig));
1313   }
1314 
GetFieldID(JNIEnv * env,jclass c,const char * name,const char * sig)1315   static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1316     CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1317     return CHECK_JNI_EXIT("f", baseEnv(env)->GetFieldID(env, c, name, sig));
1318   }
1319 
GetStaticMethodID(JNIEnv * env,jclass c,const char * name,const char * sig)1320   static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1321     CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1322     return CHECK_JNI_EXIT("m", baseEnv(env)->GetStaticMethodID(env, c, name, sig));
1323   }
1324 
GetStaticFieldID(JNIEnv * env,jclass c,const char * name,const char * sig)1325   static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1326     CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1327     return CHECK_JNI_EXIT("f", baseEnv(env)->GetStaticFieldID(env, c, name, sig));
1328   }
1329 
1330 #define FIELD_ACCESSORS(_ctype, _jname, _type) \
1331     static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1332         CHECK_JNI_ENTRY(kFlag_Default, "Ecf", env, c, fid); \
1333         sc.CheckStaticFieldID(c, fid); \
1334         return CHECK_JNI_EXIT(_type, baseEnv(env)->GetStatic##_jname##Field(env, c, fid)); \
1335     } \
1336     static _ctype Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1337         CHECK_JNI_ENTRY(kFlag_Default, "ELf", env, obj, fid); \
1338         sc.CheckInstanceFieldID(obj, fid); \
1339         return CHECK_JNI_EXIT(_type, baseEnv(env)->Get##_jname##Field(env, obj, fid)); \
1340     } \
1341     static void SetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid, _ctype value) { \
1342         CHECK_JNI_ENTRY(kFlag_Default, "Ecf" _type, env, c, fid, value); \
1343         sc.CheckStaticFieldID(c, fid); \
1344         /* "value" arg only used when type == ref */ \
1345         sc.CheckFieldType((jobject)(uint32_t)value, fid, _type[0], true); \
1346         baseEnv(env)->SetStatic##_jname##Field(env, c, fid, value); \
1347         CHECK_JNI_EXIT_VOID(); \
1348     } \
1349     static void Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid, _ctype value) { \
1350         CHECK_JNI_ENTRY(kFlag_Default, "ELf" _type, env, obj, fid, value); \
1351         sc.CheckInstanceFieldID(obj, fid); \
1352         /* "value" arg only used when type == ref */ \
1353         sc.CheckFieldType((jobject)(uint32_t) value, fid, _type[0], false); \
1354         baseEnv(env)->Set##_jname##Field(env, obj, fid, value); \
1355         CHECK_JNI_EXIT_VOID(); \
1356     }
1357 
1358 FIELD_ACCESSORS(jobject, Object, "L");
1359 FIELD_ACCESSORS(jboolean, Boolean, "Z");
1360 FIELD_ACCESSORS(jbyte, Byte, "B");
1361 FIELD_ACCESSORS(jchar, Char, "C");
1362 FIELD_ACCESSORS(jshort, Short, "S");
1363 FIELD_ACCESSORS(jint, Int, "I");
1364 FIELD_ACCESSORS(jlong, Long, "J");
1365 FIELD_ACCESSORS(jfloat, Float, "F");
1366 FIELD_ACCESSORS(jdouble, Double, "D");
1367 
1368 #define CALL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1369     /* Virtual... */ \
1370     static _ctype Call##_jname##Method(JNIEnv* env, jobject obj, \
1371         jmethodID mid, ...) \
1372     { \
1373         CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1374         sc.CheckSig(mid, _retsig, false); \
1375         sc.CheckVirtualMethod(obj, mid); \
1376         _retdecl; \
1377         va_list args; \
1378         va_start(args, mid); \
1379         _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
1380         va_end(args); \
1381         _retok; \
1382     } \
1383     static _ctype Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1384         jmethodID mid, va_list args) \
1385     { \
1386         CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1387         sc.CheckSig(mid, _retsig, false); \
1388         sc.CheckVirtualMethod(obj, mid); \
1389         _retdecl; \
1390         _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
1391         _retok; \
1392     } \
1393     static _ctype Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1394         jmethodID mid, jvalue* args) \
1395     { \
1396         CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1397         sc.CheckSig(mid, _retsig, false); \
1398         sc.CheckVirtualMethod(obj, mid); \
1399         _retdecl; \
1400         _retasgn(baseEnv(env)->Call##_jname##MethodA(env, obj, mid, args)); \
1401         _retok; \
1402     } \
1403     /* Non-virtual... */ \
1404     static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, \
1405         jobject obj, jclass c, jmethodID mid, ...) \
1406     { \
1407         CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
1408         sc.CheckSig(mid, _retsig, false); \
1409         sc.CheckVirtualMethod(obj, mid); \
1410         _retdecl; \
1411         va_list args; \
1412         va_start(args, mid); \
1413         _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
1414         va_end(args); \
1415         _retok; \
1416     } \
1417     static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1418         jobject obj, jclass c, jmethodID mid, va_list args) \
1419     { \
1420         CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
1421         sc.CheckSig(mid, _retsig, false); \
1422         sc.CheckVirtualMethod(obj, mid); \
1423         _retdecl; \
1424         _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
1425         _retok; \
1426     } \
1427     static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1428         jobject obj, jclass c, jmethodID mid, jvalue* args) \
1429     { \
1430         CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
1431         sc.CheckSig(mid, _retsig, false); \
1432         sc.CheckVirtualMethod(obj, mid); \
1433         _retdecl; \
1434         _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj, c, mid, args)); \
1435         _retok; \
1436     } \
1437     /* Static... */ \
1438     static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass c, jmethodID mid, ...) \
1439     { \
1440         CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
1441         sc.CheckSig(mid, _retsig, true); \
1442         sc.CheckStaticMethod(c, mid); \
1443         _retdecl; \
1444         va_list args; \
1445         va_start(args, mid); \
1446         _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
1447         va_end(args); \
1448         _retok; \
1449     } \
1450     static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list args) \
1451     { \
1452         CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
1453         sc.CheckSig(mid, _retsig, true); \
1454         sc.CheckStaticMethod(c, mid); \
1455         _retdecl; \
1456          _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
1457         _retok; \
1458     } \
1459     static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) \
1460     { \
1461         CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
1462         sc.CheckSig(mid, _retsig, true); \
1463         sc.CheckStaticMethod(c, mid); \
1464         _retdecl; \
1465         _retasgn(baseEnv(env)->CallStatic##_jname##MethodA(env, c, mid, args)); \
1466         _retok; \
1467     }
1468 
1469 #define NON_VOID_RETURN(_retsig, _ctype) return CHECK_JNI_EXIT(_retsig, (_ctype) result)
1470 #define VOID_RETURN CHECK_JNI_EXIT_VOID()
1471 
1472 CALL(jobject, Object, mirror::Object* result, result = reinterpret_cast<mirror::Object*>, NON_VOID_RETURN("L", jobject), "L");
1473 CALL(jboolean, Boolean, jboolean result, result =, NON_VOID_RETURN("Z", jboolean), "Z");
1474 CALL(jbyte, Byte, jbyte result, result =, NON_VOID_RETURN("B", jbyte), "B");
1475 CALL(jchar, Char, jchar result, result =, NON_VOID_RETURN("C", jchar), "C");
1476 CALL(jshort, Short, jshort result, result =, NON_VOID_RETURN("S", jshort), "S");
1477 CALL(jint, Int, jint result, result =, NON_VOID_RETURN("I", jint), "I");
1478 CALL(jlong, Long, jlong result, result =, NON_VOID_RETURN("J", jlong), "J");
1479 CALL(jfloat, Float, jfloat result, result =, NON_VOID_RETURN("F", jfloat), "F");
1480 CALL(jdouble, Double, jdouble result, result =, NON_VOID_RETURN("D", jdouble), "D");
1481 CALL(void, Void, , , VOID_RETURN, "V");
1482 
NewString(JNIEnv * env,const jchar * unicodeChars,jsize len)1483   static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
1484     CHECK_JNI_ENTRY(kFlag_Default, "Epz", env, unicodeChars, len);
1485     return CHECK_JNI_EXIT("s", baseEnv(env)->NewString(env, unicodeChars, len));
1486   }
1487 
GetStringLength(JNIEnv * env,jstring string)1488   static jsize GetStringLength(JNIEnv* env, jstring string) {
1489     CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1490     return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringLength(env, string));
1491   }
1492 
GetStringChars(JNIEnv * env,jstring java_string,jboolean * isCopy)1493   static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1494     CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy);
1495     const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy);
1496     if (sc.ForceCopy() && result != NULL) {
1497       mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
1498       int byteCount = s->GetLength() * 2;
1499       result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
1500       if (isCopy != NULL) {
1501         *isCopy = JNI_TRUE;
1502       }
1503     }
1504     return CHECK_JNI_EXIT("p", result);
1505   }
1506 
ReleaseStringChars(JNIEnv * env,jstring string,const jchar * chars)1507   static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
1508     CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Esp", env, string, chars);
1509     sc.CheckNonNull(chars);
1510     if (sc.ForceCopy()) {
1511       GuardedCopy::Check(__FUNCTION__, chars, false);
1512       chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(chars)));
1513     }
1514     baseEnv(env)->ReleaseStringChars(env, string, chars);
1515     CHECK_JNI_EXIT_VOID();
1516   }
1517 
NewStringUTF(JNIEnv * env,const char * bytes)1518   static jstring NewStringUTF(JNIEnv* env, const char* bytes) {
1519     CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, bytes);  // TODO: show pointer and truncate string.
1520     return CHECK_JNI_EXIT("s", baseEnv(env)->NewStringUTF(env, bytes));
1521   }
1522 
GetStringUTFLength(JNIEnv * env,jstring string)1523   static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
1524     CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1525     return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringUTFLength(env, string));
1526   }
1527 
GetStringUTFChars(JNIEnv * env,jstring string,jboolean * isCopy)1528   static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
1529     CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, string, isCopy);
1530     const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
1531     if (sc.ForceCopy() && result != NULL) {
1532       result = (const char*) GuardedCopy::Create(result, strlen(result) + 1, false);
1533       if (isCopy != NULL) {
1534         *isCopy = JNI_TRUE;
1535       }
1536     }
1537     return CHECK_JNI_EXIT("u", result);  // TODO: show pointer and truncate string.
1538   }
1539 
ReleaseStringUTFChars(JNIEnv * env,jstring string,const char * utf)1540   static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
1541     CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_Release, "Esu", env, string, utf);  // TODO: show pointer and truncate string.
1542     if (sc.ForceCopy()) {
1543       GuardedCopy::Check(__FUNCTION__, utf, false);
1544       utf = reinterpret_cast<const char*>(GuardedCopy::Destroy(const_cast<char*>(utf)));
1545     }
1546     baseEnv(env)->ReleaseStringUTFChars(env, string, utf);
1547     CHECK_JNI_EXIT_VOID();
1548   }
1549 
GetArrayLength(JNIEnv * env,jarray array)1550   static jsize GetArrayLength(JNIEnv* env, jarray array) {
1551     CHECK_JNI_ENTRY(kFlag_CritOkay, "Ea", env, array);
1552     return CHECK_JNI_EXIT("I", baseEnv(env)->GetArrayLength(env, array));
1553   }
1554 
NewObjectArray(JNIEnv * env,jsize length,jclass elementClass,jobject initialElement)1555   static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass elementClass, jobject initialElement) {
1556     CHECK_JNI_ENTRY(kFlag_Default, "EzcL", env, length, elementClass, initialElement);
1557     return CHECK_JNI_EXIT("a", baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement));
1558   }
1559 
GetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index)1560   static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
1561     CHECK_JNI_ENTRY(kFlag_Default, "EaI", env, array, index);
1562     return CHECK_JNI_EXIT("L", baseEnv(env)->GetObjectArrayElement(env, array, index));
1563   }
1564 
SetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index,jobject value)1565   static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
1566     CHECK_JNI_ENTRY(kFlag_Default, "EaIL", env, array, index, value);
1567     baseEnv(env)->SetObjectArrayElement(env, array, index, value);
1568     CHECK_JNI_EXIT_VOID();
1569   }
1570 
1571 #define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1572     static _artype New##_jname##Array(JNIEnv* env, jsize length) { \
1573         CHECK_JNI_ENTRY(kFlag_Default, "Ez", env, length); \
1574         return CHECK_JNI_EXIT("a", baseEnv(env)->New##_jname##Array(env, length)); \
1575     }
1576 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1577 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1578 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1579 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1580 NEW_PRIMITIVE_ARRAY(jintArray, Int);
1581 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1582 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1583 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1584 
1585 struct ForceCopyGetChecker {
1586  public:
ForceCopyGetCheckerart::CheckJNI::ForceCopyGetChecker1587   ForceCopyGetChecker(ScopedCheck& sc, jboolean* isCopy) {
1588     force_copy = sc.ForceCopy();
1589     no_copy = 0;
1590     if (force_copy && isCopy != NULL) {
1591       // Capture this before the base call tramples on it.
1592       no_copy = *reinterpret_cast<uint32_t*>(isCopy);
1593     }
1594   }
1595 
1596   template<typename ResultT>
Checkart::CheckJNI::ForceCopyGetChecker1597   ResultT Check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) {
1598     if (force_copy && result != NULL) {
1599       if (no_copy != kNoCopyMagic) {
1600         result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
1601       }
1602     }
1603     return result;
1604   }
1605 
1606   uint32_t no_copy;
1607   bool force_copy;
1608 };
1609 
1610 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1611   static _ctype* Get##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, jboolean* isCopy) { \
1612     CHECK_JNI_ENTRY(kFlag_Default, "Eap", env, array, isCopy); \
1613     _ctype* result = ForceCopyGetChecker(sc, isCopy).Check(env, array, isCopy, baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy)); \
1614     return CHECK_JNI_EXIT("p", result); \
1615   }
1616 
1617 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1618   static void Release##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, _ctype* elems, jint mode) { \
1619     CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Eapr", env, array, elems, mode); \
1620     sc.CheckNonNull(elems); \
1621     if (sc.ForceCopy()) { \
1622       ReleaseGuardedPACopy(env, array, elems, mode); \
1623     } \
1624     baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \
1625     CHECK_JNI_EXIT_VOID(); \
1626   }
1627 
1628 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1629     static void Get##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, _ctype* buf) { \
1630         CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1631         baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \
1632         CHECK_JNI_EXIT_VOID(); \
1633     }
1634 
1635 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1636     static void Set##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \
1637         CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1638         baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \
1639         CHECK_JNI_EXIT_VOID(); \
1640     }
1641 
1642 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1643     GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1644     RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1645     GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1646     SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1647 
1648 // TODO: verify primitive array type matches call type.
1649 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1650 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1651 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1652 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1653 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1654 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1655 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1656 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1657 
RegisterNatives(JNIEnv * env,jclass c,const JNINativeMethod * methods,jint nMethods)1658   static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1659     CHECK_JNI_ENTRY(kFlag_Default, "EcpI", env, c, methods, nMethods);
1660     return CHECK_JNI_EXIT("I", baseEnv(env)->RegisterNatives(env, c, methods, nMethods));
1661   }
1662 
UnregisterNatives(JNIEnv * env,jclass c)1663   static jint UnregisterNatives(JNIEnv* env, jclass c) {
1664     CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1665     return CHECK_JNI_EXIT("I", baseEnv(env)->UnregisterNatives(env, c));
1666   }
1667 
MonitorEnter(JNIEnv * env,jobject obj)1668   static jint MonitorEnter(JNIEnv* env, jobject obj) {
1669     CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1670     if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
1671       return JNI_ERR;  // Only for jni_internal_test. Real code will have aborted already.
1672     }
1673     return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorEnter(env, obj));
1674   }
1675 
MonitorExit(JNIEnv * env,jobject obj)1676   static jint MonitorExit(JNIEnv* env, jobject obj) {
1677     CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, obj);
1678     if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
1679       return JNI_ERR;  // Only for jni_internal_test. Real code will have aborted already.
1680     }
1681     return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorExit(env, obj));
1682   }
1683 
GetJavaVM(JNIEnv * env,JavaVM ** vm)1684   static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1685     CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, vm);
1686     return CHECK_JNI_EXIT("I", baseEnv(env)->GetJavaVM(env, vm));
1687   }
1688 
GetStringRegion(JNIEnv * env,jstring str,jsize start,jsize len,jchar * buf)1689   static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
1690     CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1691     baseEnv(env)->GetStringRegion(env, str, start, len, buf);
1692     CHECK_JNI_EXIT_VOID();
1693   }
1694 
GetStringUTFRegion(JNIEnv * env,jstring str,jsize start,jsize len,char * buf)1695   static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
1696     CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1697     baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf);
1698     CHECK_JNI_EXIT_VOID();
1699   }
1700 
GetPrimitiveArrayCritical(JNIEnv * env,jarray array,jboolean * isCopy)1701   static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
1702     CHECK_JNI_ENTRY(kFlag_CritGet, "Eap", env, array, isCopy);
1703     void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
1704     if (sc.ForceCopy() && result != NULL) {
1705       result = CreateGuardedPACopy(env, array, isCopy);
1706     }
1707     return CHECK_JNI_EXIT("p", result);
1708   }
1709 
ReleasePrimitiveArrayCritical(JNIEnv * env,jarray array,void * carray,jint mode)1710   static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
1711     CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Eapr", env, array, carray, mode);
1712     sc.CheckNonNull(carray);
1713     if (sc.ForceCopy()) {
1714       ReleaseGuardedPACopy(env, array, carray, mode);
1715     }
1716     baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1717     CHECK_JNI_EXIT_VOID();
1718   }
1719 
GetStringCritical(JNIEnv * env,jstring java_string,jboolean * isCopy)1720   static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1721     CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy);
1722     const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy);
1723     if (sc.ForceCopy() && result != NULL) {
1724       mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
1725       int byteCount = s->GetLength() * 2;
1726       result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
1727       if (isCopy != NULL) {
1728         *isCopy = JNI_TRUE;
1729       }
1730     }
1731     return CHECK_JNI_EXIT("p", result);
1732   }
1733 
ReleaseStringCritical(JNIEnv * env,jstring string,const jchar * carray)1734   static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) {
1735     CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Esp", env, string, carray);
1736     sc.CheckNonNull(carray);
1737     if (sc.ForceCopy()) {
1738       GuardedCopy::Check(__FUNCTION__, carray, false);
1739       carray = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(carray)));
1740     }
1741     baseEnv(env)->ReleaseStringCritical(env, string, carray);
1742     CHECK_JNI_EXIT_VOID();
1743   }
1744 
NewWeakGlobalRef(JNIEnv * env,jobject obj)1745   static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
1746     CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1747     return CHECK_JNI_EXIT("L", baseEnv(env)->NewWeakGlobalRef(env, obj));
1748   }
1749 
ExceptionCheck(JNIEnv * env)1750   static jboolean ExceptionCheck(JNIEnv* env) {
1751     CHECK_JNI_ENTRY(kFlag_CritOkay | kFlag_ExcepOkay, "E", env);
1752     return CHECK_JNI_EXIT("b", baseEnv(env)->ExceptionCheck(env));
1753   }
1754 
GetObjectRefType(JNIEnv * env,jobject obj)1755   static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1756     // Note: we use "Ep" rather than "EL" because this is the one JNI function
1757     // that it's okay to pass an invalid reference to.
1758     CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, obj);
1759     // TODO: proper decoding of jobjectRefType!
1760     return CHECK_JNI_EXIT("I", baseEnv(env)->GetObjectRefType(env, obj));
1761   }
1762 
NewDirectByteBuffer(JNIEnv * env,void * address,jlong capacity)1763   static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
1764     CHECK_JNI_ENTRY(kFlag_Default, "EpJ", env, address, capacity);
1765     if (address == NULL) {
1766       JniAbortF(__FUNCTION__, "non-nullable address is NULL");
1767     }
1768     if (capacity <= 0) {
1769       JniAbortF(__FUNCTION__, "capacity must be greater than 0: %lld", capacity);
1770     }
1771     return CHECK_JNI_EXIT("L", baseEnv(env)->NewDirectByteBuffer(env, address, capacity));
1772   }
1773 
GetDirectBufferAddress(JNIEnv * env,jobject buf)1774   static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
1775     CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1776     // TODO: check that 'buf' is a java.nio.Buffer.
1777     return CHECK_JNI_EXIT("p", baseEnv(env)->GetDirectBufferAddress(env, buf));
1778   }
1779 
GetDirectBufferCapacity(JNIEnv * env,jobject buf)1780   static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
1781     CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1782     // TODO: check that 'buf' is a java.nio.Buffer.
1783     return CHECK_JNI_EXIT("J", baseEnv(env)->GetDirectBufferCapacity(env, buf));
1784   }
1785 
1786  private:
baseEnv(JNIEnv * env)1787   static inline const JNINativeInterface* baseEnv(JNIEnv* env) {
1788     return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
1789   }
1790 };
1791 
1792 const JNINativeInterface gCheckNativeInterface = {
1793   NULL,  // reserved0.
1794   NULL,  // reserved1.
1795   NULL,  // reserved2.
1796   NULL,  // reserved3.
1797   CheckJNI::GetVersion,
1798   CheckJNI::DefineClass,
1799   CheckJNI::FindClass,
1800   CheckJNI::FromReflectedMethod,
1801   CheckJNI::FromReflectedField,
1802   CheckJNI::ToReflectedMethod,
1803   CheckJNI::GetSuperclass,
1804   CheckJNI::IsAssignableFrom,
1805   CheckJNI::ToReflectedField,
1806   CheckJNI::Throw,
1807   CheckJNI::ThrowNew,
1808   CheckJNI::ExceptionOccurred,
1809   CheckJNI::ExceptionDescribe,
1810   CheckJNI::ExceptionClear,
1811   CheckJNI::FatalError,
1812   CheckJNI::PushLocalFrame,
1813   CheckJNI::PopLocalFrame,
1814   CheckJNI::NewGlobalRef,
1815   CheckJNI::DeleteGlobalRef,
1816   CheckJNI::DeleteLocalRef,
1817   CheckJNI::IsSameObject,
1818   CheckJNI::NewLocalRef,
1819   CheckJNI::EnsureLocalCapacity,
1820   CheckJNI::AllocObject,
1821   CheckJNI::NewObject,
1822   CheckJNI::NewObjectV,
1823   CheckJNI::NewObjectA,
1824   CheckJNI::GetObjectClass,
1825   CheckJNI::IsInstanceOf,
1826   CheckJNI::GetMethodID,
1827   CheckJNI::CallObjectMethod,
1828   CheckJNI::CallObjectMethodV,
1829   CheckJNI::CallObjectMethodA,
1830   CheckJNI::CallBooleanMethod,
1831   CheckJNI::CallBooleanMethodV,
1832   CheckJNI::CallBooleanMethodA,
1833   CheckJNI::CallByteMethod,
1834   CheckJNI::CallByteMethodV,
1835   CheckJNI::CallByteMethodA,
1836   CheckJNI::CallCharMethod,
1837   CheckJNI::CallCharMethodV,
1838   CheckJNI::CallCharMethodA,
1839   CheckJNI::CallShortMethod,
1840   CheckJNI::CallShortMethodV,
1841   CheckJNI::CallShortMethodA,
1842   CheckJNI::CallIntMethod,
1843   CheckJNI::CallIntMethodV,
1844   CheckJNI::CallIntMethodA,
1845   CheckJNI::CallLongMethod,
1846   CheckJNI::CallLongMethodV,
1847   CheckJNI::CallLongMethodA,
1848   CheckJNI::CallFloatMethod,
1849   CheckJNI::CallFloatMethodV,
1850   CheckJNI::CallFloatMethodA,
1851   CheckJNI::CallDoubleMethod,
1852   CheckJNI::CallDoubleMethodV,
1853   CheckJNI::CallDoubleMethodA,
1854   CheckJNI::CallVoidMethod,
1855   CheckJNI::CallVoidMethodV,
1856   CheckJNI::CallVoidMethodA,
1857   CheckJNI::CallNonvirtualObjectMethod,
1858   CheckJNI::CallNonvirtualObjectMethodV,
1859   CheckJNI::CallNonvirtualObjectMethodA,
1860   CheckJNI::CallNonvirtualBooleanMethod,
1861   CheckJNI::CallNonvirtualBooleanMethodV,
1862   CheckJNI::CallNonvirtualBooleanMethodA,
1863   CheckJNI::CallNonvirtualByteMethod,
1864   CheckJNI::CallNonvirtualByteMethodV,
1865   CheckJNI::CallNonvirtualByteMethodA,
1866   CheckJNI::CallNonvirtualCharMethod,
1867   CheckJNI::CallNonvirtualCharMethodV,
1868   CheckJNI::CallNonvirtualCharMethodA,
1869   CheckJNI::CallNonvirtualShortMethod,
1870   CheckJNI::CallNonvirtualShortMethodV,
1871   CheckJNI::CallNonvirtualShortMethodA,
1872   CheckJNI::CallNonvirtualIntMethod,
1873   CheckJNI::CallNonvirtualIntMethodV,
1874   CheckJNI::CallNonvirtualIntMethodA,
1875   CheckJNI::CallNonvirtualLongMethod,
1876   CheckJNI::CallNonvirtualLongMethodV,
1877   CheckJNI::CallNonvirtualLongMethodA,
1878   CheckJNI::CallNonvirtualFloatMethod,
1879   CheckJNI::CallNonvirtualFloatMethodV,
1880   CheckJNI::CallNonvirtualFloatMethodA,
1881   CheckJNI::CallNonvirtualDoubleMethod,
1882   CheckJNI::CallNonvirtualDoubleMethodV,
1883   CheckJNI::CallNonvirtualDoubleMethodA,
1884   CheckJNI::CallNonvirtualVoidMethod,
1885   CheckJNI::CallNonvirtualVoidMethodV,
1886   CheckJNI::CallNonvirtualVoidMethodA,
1887   CheckJNI::GetFieldID,
1888   CheckJNI::GetObjectField,
1889   CheckJNI::GetBooleanField,
1890   CheckJNI::GetByteField,
1891   CheckJNI::GetCharField,
1892   CheckJNI::GetShortField,
1893   CheckJNI::GetIntField,
1894   CheckJNI::GetLongField,
1895   CheckJNI::GetFloatField,
1896   CheckJNI::GetDoubleField,
1897   CheckJNI::SetObjectField,
1898   CheckJNI::SetBooleanField,
1899   CheckJNI::SetByteField,
1900   CheckJNI::SetCharField,
1901   CheckJNI::SetShortField,
1902   CheckJNI::SetIntField,
1903   CheckJNI::SetLongField,
1904   CheckJNI::SetFloatField,
1905   CheckJNI::SetDoubleField,
1906   CheckJNI::GetStaticMethodID,
1907   CheckJNI::CallStaticObjectMethod,
1908   CheckJNI::CallStaticObjectMethodV,
1909   CheckJNI::CallStaticObjectMethodA,
1910   CheckJNI::CallStaticBooleanMethod,
1911   CheckJNI::CallStaticBooleanMethodV,
1912   CheckJNI::CallStaticBooleanMethodA,
1913   CheckJNI::CallStaticByteMethod,
1914   CheckJNI::CallStaticByteMethodV,
1915   CheckJNI::CallStaticByteMethodA,
1916   CheckJNI::CallStaticCharMethod,
1917   CheckJNI::CallStaticCharMethodV,
1918   CheckJNI::CallStaticCharMethodA,
1919   CheckJNI::CallStaticShortMethod,
1920   CheckJNI::CallStaticShortMethodV,
1921   CheckJNI::CallStaticShortMethodA,
1922   CheckJNI::CallStaticIntMethod,
1923   CheckJNI::CallStaticIntMethodV,
1924   CheckJNI::CallStaticIntMethodA,
1925   CheckJNI::CallStaticLongMethod,
1926   CheckJNI::CallStaticLongMethodV,
1927   CheckJNI::CallStaticLongMethodA,
1928   CheckJNI::CallStaticFloatMethod,
1929   CheckJNI::CallStaticFloatMethodV,
1930   CheckJNI::CallStaticFloatMethodA,
1931   CheckJNI::CallStaticDoubleMethod,
1932   CheckJNI::CallStaticDoubleMethodV,
1933   CheckJNI::CallStaticDoubleMethodA,
1934   CheckJNI::CallStaticVoidMethod,
1935   CheckJNI::CallStaticVoidMethodV,
1936   CheckJNI::CallStaticVoidMethodA,
1937   CheckJNI::GetStaticFieldID,
1938   CheckJNI::GetStaticObjectField,
1939   CheckJNI::GetStaticBooleanField,
1940   CheckJNI::GetStaticByteField,
1941   CheckJNI::GetStaticCharField,
1942   CheckJNI::GetStaticShortField,
1943   CheckJNI::GetStaticIntField,
1944   CheckJNI::GetStaticLongField,
1945   CheckJNI::GetStaticFloatField,
1946   CheckJNI::GetStaticDoubleField,
1947   CheckJNI::SetStaticObjectField,
1948   CheckJNI::SetStaticBooleanField,
1949   CheckJNI::SetStaticByteField,
1950   CheckJNI::SetStaticCharField,
1951   CheckJNI::SetStaticShortField,
1952   CheckJNI::SetStaticIntField,
1953   CheckJNI::SetStaticLongField,
1954   CheckJNI::SetStaticFloatField,
1955   CheckJNI::SetStaticDoubleField,
1956   CheckJNI::NewString,
1957   CheckJNI::GetStringLength,
1958   CheckJNI::GetStringChars,
1959   CheckJNI::ReleaseStringChars,
1960   CheckJNI::NewStringUTF,
1961   CheckJNI::GetStringUTFLength,
1962   CheckJNI::GetStringUTFChars,
1963   CheckJNI::ReleaseStringUTFChars,
1964   CheckJNI::GetArrayLength,
1965   CheckJNI::NewObjectArray,
1966   CheckJNI::GetObjectArrayElement,
1967   CheckJNI::SetObjectArrayElement,
1968   CheckJNI::NewBooleanArray,
1969   CheckJNI::NewByteArray,
1970   CheckJNI::NewCharArray,
1971   CheckJNI::NewShortArray,
1972   CheckJNI::NewIntArray,
1973   CheckJNI::NewLongArray,
1974   CheckJNI::NewFloatArray,
1975   CheckJNI::NewDoubleArray,
1976   CheckJNI::GetBooleanArrayElements,
1977   CheckJNI::GetByteArrayElements,
1978   CheckJNI::GetCharArrayElements,
1979   CheckJNI::GetShortArrayElements,
1980   CheckJNI::GetIntArrayElements,
1981   CheckJNI::GetLongArrayElements,
1982   CheckJNI::GetFloatArrayElements,
1983   CheckJNI::GetDoubleArrayElements,
1984   CheckJNI::ReleaseBooleanArrayElements,
1985   CheckJNI::ReleaseByteArrayElements,
1986   CheckJNI::ReleaseCharArrayElements,
1987   CheckJNI::ReleaseShortArrayElements,
1988   CheckJNI::ReleaseIntArrayElements,
1989   CheckJNI::ReleaseLongArrayElements,
1990   CheckJNI::ReleaseFloatArrayElements,
1991   CheckJNI::ReleaseDoubleArrayElements,
1992   CheckJNI::GetBooleanArrayRegion,
1993   CheckJNI::GetByteArrayRegion,
1994   CheckJNI::GetCharArrayRegion,
1995   CheckJNI::GetShortArrayRegion,
1996   CheckJNI::GetIntArrayRegion,
1997   CheckJNI::GetLongArrayRegion,
1998   CheckJNI::GetFloatArrayRegion,
1999   CheckJNI::GetDoubleArrayRegion,
2000   CheckJNI::SetBooleanArrayRegion,
2001   CheckJNI::SetByteArrayRegion,
2002   CheckJNI::SetCharArrayRegion,
2003   CheckJNI::SetShortArrayRegion,
2004   CheckJNI::SetIntArrayRegion,
2005   CheckJNI::SetLongArrayRegion,
2006   CheckJNI::SetFloatArrayRegion,
2007   CheckJNI::SetDoubleArrayRegion,
2008   CheckJNI::RegisterNatives,
2009   CheckJNI::UnregisterNatives,
2010   CheckJNI::MonitorEnter,
2011   CheckJNI::MonitorExit,
2012   CheckJNI::GetJavaVM,
2013   CheckJNI::GetStringRegion,
2014   CheckJNI::GetStringUTFRegion,
2015   CheckJNI::GetPrimitiveArrayCritical,
2016   CheckJNI::ReleasePrimitiveArrayCritical,
2017   CheckJNI::GetStringCritical,
2018   CheckJNI::ReleaseStringCritical,
2019   CheckJNI::NewWeakGlobalRef,
2020   CheckJNI::DeleteWeakGlobalRef,
2021   CheckJNI::ExceptionCheck,
2022   CheckJNI::NewDirectByteBuffer,
2023   CheckJNI::GetDirectBufferAddress,
2024   CheckJNI::GetDirectBufferCapacity,
2025   CheckJNI::GetObjectRefType,
2026 };
2027 
GetCheckJniNativeInterface()2028 const JNINativeInterface* GetCheckJniNativeInterface() {
2029   return &gCheckNativeInterface;
2030 }
2031 
2032 class CheckJII {
2033  public:
DestroyJavaVM(JavaVM * vm)2034   static jint DestroyJavaVM(JavaVM* vm) {
2035     ScopedCheck sc(vm, false, __FUNCTION__);
2036     sc.Check(true, "v", vm);
2037     return CHECK_JNI_EXIT("I", BaseVm(vm)->DestroyJavaVM(vm));
2038   }
2039 
AttachCurrentThread(JavaVM * vm,JNIEnv ** p_env,void * thr_args)2040   static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2041     ScopedCheck sc(vm, false, __FUNCTION__);
2042     sc.Check(true, "vpp", vm, p_env, thr_args);
2043     return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args));
2044   }
2045 
AttachCurrentThreadAsDaemon(JavaVM * vm,JNIEnv ** p_env,void * thr_args)2046   static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2047     ScopedCheck sc(vm, false, __FUNCTION__);
2048     sc.Check(true, "vpp", vm, p_env, thr_args);
2049     return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args));
2050   }
2051 
DetachCurrentThread(JavaVM * vm)2052   static jint DetachCurrentThread(JavaVM* vm) {
2053     ScopedCheck sc(vm, true, __FUNCTION__);
2054     sc.Check(true, "v", vm);
2055     return CHECK_JNI_EXIT("I", BaseVm(vm)->DetachCurrentThread(vm));
2056   }
2057 
GetEnv(JavaVM * vm,void ** env,jint version)2058   static jint GetEnv(JavaVM* vm, void** env, jint version) {
2059     ScopedCheck sc(vm, true, __FUNCTION__);
2060     sc.Check(true, "vpI", vm);
2061     return CHECK_JNI_EXIT("I", BaseVm(vm)->GetEnv(vm, env, version));
2062   }
2063 
2064  private:
BaseVm(JavaVM * vm)2065   static inline const JNIInvokeInterface* BaseVm(JavaVM* vm) {
2066     return reinterpret_cast<JavaVMExt*>(vm)->unchecked_functions;
2067   }
2068 };
2069 
2070 const JNIInvokeInterface gCheckInvokeInterface = {
2071   NULL,  // reserved0
2072   NULL,  // reserved1
2073   NULL,  // reserved2
2074   CheckJII::DestroyJavaVM,
2075   CheckJII::AttachCurrentThread,
2076   CheckJII::DetachCurrentThread,
2077   CheckJII::GetEnv,
2078   CheckJII::AttachCurrentThreadAsDaemon
2079 };
2080 
GetCheckJniInvokeInterface()2081 const JNIInvokeInterface* GetCheckJniInvokeInterface() {
2082   return &gCheckInvokeInterface;
2083 }
2084 
2085 }  // namespace art
2086