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