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
38namespace art {
39
40static 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
69static 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
75void 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
88static 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
118static 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
130static 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
154class ScopedCheck {
155 public:
156  // For JNIEnv* functions.
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.
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
172  ~ScopedCheck() UNLOCK_FUNCTION(Locks::mutator_lock_) {}
173
174  const ScopedObjectAccess& soa() {
175    return soa_;
176  }
177
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.
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   */
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   */
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   */
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   */
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   */
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   */
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 (!c->IsAssignableFrom(m->GetDeclaringClass())) {
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   */
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   */
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   */
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.
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   */
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
693  void CheckLengthPositive(jsize length) {
694    if (length < 0) {
695      JniAbortF(function_name_, "negative jsize: %d", length);
696    }
697  }
698
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
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   */
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   */
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
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.
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
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 */
919struct 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 */
926  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   */
936  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   */
969  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   */
983  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:
1044  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
1052  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
1065  static const uint8_t* ActualBuffer(const void* dataBuf) {
1066    return reinterpret_cast<const uint8_t*>(dataBuf) - kGuardLen / 2;
1067  }
1068
1069  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.
1074  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 */
1083static 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 */
1100static 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
1125class CheckJNI {
1126 public:
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1358FIELD_ACCESSORS(jobject, Object, "L");
1359FIELD_ACCESSORS(jboolean, Boolean, "Z");
1360FIELD_ACCESSORS(jbyte, Byte, "B");
1361FIELD_ACCESSORS(jchar, Char, "C");
1362FIELD_ACCESSORS(jshort, Short, "S");
1363FIELD_ACCESSORS(jint, Int, "I");
1364FIELD_ACCESSORS(jlong, Long, "J");
1365FIELD_ACCESSORS(jfloat, Float, "F");
1366FIELD_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
1472CALL(jobject, Object, mirror::Object* result, result = reinterpret_cast<mirror::Object*>, NON_VOID_RETURN("L", jobject), "L");
1473CALL(jboolean, Boolean, jboolean result, result =, NON_VOID_RETURN("Z", jboolean), "Z");
1474CALL(jbyte, Byte, jbyte result, result =, NON_VOID_RETURN("B", jbyte), "B");
1475CALL(jchar, Char, jchar result, result =, NON_VOID_RETURN("C", jchar), "C");
1476CALL(jshort, Short, jshort result, result =, NON_VOID_RETURN("S", jshort), "S");
1477CALL(jint, Int, jint result, result =, NON_VOID_RETURN("I", jint), "I");
1478CALL(jlong, Long, jlong result, result =, NON_VOID_RETURN("J", jlong), "J");
1479CALL(jfloat, Float, jfloat result, result =, NON_VOID_RETURN("F", jfloat), "F");
1480CALL(jdouble, Double, jdouble result, result =, NON_VOID_RETURN("D", jdouble), "D");
1481CALL(void, Void, , , VOID_RETURN, "V");
1482
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
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
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
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
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
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
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
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
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
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
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
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    }
1576NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1577NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1578NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1579NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1580NEW_PRIMITIVE_ARRAY(jintArray, Int);
1581NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1582NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1583NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1584
1585struct ForceCopyGetChecker {
1586 public:
1587  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>
1597  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.
1649PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1650PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1651PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1652PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1653PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1654PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1655PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1656PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1657
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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:
1787  static inline const JNINativeInterface* baseEnv(JNIEnv* env) {
1788    return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
1789  }
1790};
1791
1792const 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
2028const JNINativeInterface* GetCheckJniNativeInterface() {
2029  return &gCheckNativeInterface;
2030}
2031
2032class CheckJII {
2033 public:
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
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
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
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
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:
2065  static inline const JNIInvokeInterface* BaseVm(JavaVM* vm) {
2066    return reinterpret_cast<JavaVMExt*>(vm)->unchecked_functions;
2067  }
2068};
2069
2070const 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
2081const JNIInvokeInterface* GetCheckJniInvokeInterface() {
2082  return &gCheckInvokeInterface;
2083}
2084
2085}  // namespace art
2086