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