1/*
2 * Copyright (C) 2011 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 <dlfcn.h>
20
21#include <cstdarg>
22#include <utility>
23#include <vector>
24
25#include "base/logging.h"
26#include "base/mutex.h"
27#include "base/stl_util.h"
28#include "base/stringpiece.h"
29#include "class_linker.h"
30#include "dex_file-inl.h"
31#include "gc/accounting/card_table-inl.h"
32#include "interpreter/interpreter.h"
33#include "invoke_arg_array_builder.h"
34#include "jni.h"
35#include "mirror/art_field-inl.h"
36#include "mirror/art_method-inl.h"
37#include "mirror/class-inl.h"
38#include "mirror/class_loader.h"
39#include "mirror/object-inl.h"
40#include "mirror/object_array-inl.h"
41#include "mirror/throwable.h"
42#include "object_utils.h"
43#include "runtime.h"
44#include "safe_map.h"
45#include "scoped_thread_state_change.h"
46#include "ScopedLocalRef.h"
47#include "thread.h"
48#include "utf.h"
49#include "UniquePtr.h"
50#include "well_known_classes.h"
51
52using ::art::mirror::ArtField;
53using ::art::mirror::ArtMethod;
54using ::art::mirror::Array;
55using ::art::mirror::BooleanArray;
56using ::art::mirror::ByteArray;
57using ::art::mirror::CharArray;
58using ::art::mirror::Class;
59using ::art::mirror::ClassLoader;
60using ::art::mirror::DoubleArray;
61using ::art::mirror::FloatArray;
62using ::art::mirror::IntArray;
63using ::art::mirror::LongArray;
64using ::art::mirror::Object;
65using ::art::mirror::ObjectArray;
66using ::art::mirror::ShortArray;
67using ::art::mirror::String;
68using ::art::mirror::Throwable;
69
70namespace art {
71
72static const size_t kMonitorsInitial = 32;  // Arbitrary.
73static const size_t kMonitorsMax = 4096;  // Arbitrary sanity check.
74
75static const size_t kLocalsInitial = 64;  // Arbitrary.
76static const size_t kLocalsMax = 512;  // Arbitrary sanity check.
77
78static const size_t kPinTableInitial = 16;  // Arbitrary.
79static const size_t kPinTableMax = 1024;  // Arbitrary sanity check.
80
81static size_t gGlobalsInitial = 512;  // Arbitrary.
82static size_t gGlobalsMax = 51200;  // Arbitrary sanity check. (Must fit in 16 bits.)
83
84static const size_t kWeakGlobalsInitial = 16;  // Arbitrary.
85static const size_t kWeakGlobalsMax = 51200;  // Arbitrary sanity check. (Must fit in 16 bits.)
86
87static jweak AddWeakGlobalReference(ScopedObjectAccess& soa, Object* obj)
88    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
89  return soa.Vm()->AddWeakGlobalReference(soa.Self(), obj);
90}
91
92static bool IsBadJniVersion(int version) {
93  // We don't support JNI_VERSION_1_1. These are the only other valid versions.
94  return version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 && version != JNI_VERSION_1_6;
95}
96
97static void CheckMethodArguments(ArtMethod* m, uint32_t* args)
98    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
99  MethodHelper mh(m);
100  const DexFile::TypeList* params = mh.GetParameterTypeList();
101  if (params == NULL) {
102    return;  // No arguments so nothing to check.
103  }
104  uint32_t offset = 0;
105  uint32_t num_params = params->Size();
106  size_t error_count = 0;
107  if (!m->IsStatic()) {
108    offset = 1;
109  }
110  for (uint32_t i = 0; i < num_params; i++) {
111    uint16_t type_idx = params->GetTypeItem(i).type_idx_;
112    Class* param_type = mh.GetClassFromTypeIdx(type_idx);
113    if (param_type == NULL) {
114      Thread* self = Thread::Current();
115      CHECK(self->IsExceptionPending());
116      LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: "
117          << mh.GetTypeDescriptorFromTypeIdx(type_idx) << "\n"
118          << self->GetException(NULL)->Dump();
119      self->ClearException();
120      ++error_count;
121    } else if (!param_type->IsPrimitive()) {
122      // TODO: check primitives are in range.
123      Object* argument = reinterpret_cast<Object*>(args[i + offset]);
124      if (argument != NULL && !argument->InstanceOf(param_type)) {
125        LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of "
126                   << PrettyTypeOf(argument) << " as argument " << (i + 1) << " to " << PrettyMethod(m);
127        ++error_count;
128      }
129    } else if (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble()) {
130      offset++;
131    }
132  }
133  if (error_count > 0) {
134    // TODO: pass the JNI function name (such as "CallVoidMethodV") through so we can call JniAbort
135    // with an argument.
136    JniAbortF(NULL, "bad arguments passed to %s (see above for details)", PrettyMethod(m).c_str());
137  }
138}
139
140void InvokeWithArgArray(const ScopedObjectAccess& soa, ArtMethod* method,
141                        ArgArray* arg_array, JValue* result, char result_type)
142    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
143  uint32_t* args = arg_array->GetArray();
144  if (UNLIKELY(soa.Env()->check_jni)) {
145    CheckMethodArguments(method, args);
146  }
147  method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, result_type);
148}
149
150static JValue InvokeWithVarArgs(const ScopedObjectAccess& soa, jobject obj,
151                                jmethodID mid, va_list args)
152    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
153  ArtMethod* method = soa.DecodeMethod(mid);
154  Object* receiver = method->IsStatic() ? NULL : soa.Decode<Object*>(obj);
155  MethodHelper mh(method);
156  JValue result;
157  ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
158  arg_array.BuildArgArray(soa, receiver, args);
159  InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()[0]);
160  return result;
161}
162
163static ArtMethod* FindVirtualMethod(Object* receiver, ArtMethod* method)
164    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
165  return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method);
166}
167
168static JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccess& soa,
169                                                  jobject obj, jmethodID mid, jvalue* args)
170    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
171  Object* receiver = soa.Decode<Object*>(obj);
172  ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
173  MethodHelper mh(method);
174  JValue result;
175  ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
176  arg_array.BuildArgArray(soa, receiver, args);
177  InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()[0]);
178  return result;
179}
180
181static JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccess& soa,
182                                                  jobject obj, jmethodID mid, va_list args)
183    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
184  Object* receiver = soa.Decode<Object*>(obj);
185  ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
186  MethodHelper mh(method);
187  JValue result;
188  ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
189  arg_array.BuildArgArray(soa, receiver, args);
190  InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()[0]);
191  return result;
192}
193
194// Section 12.3.2 of the JNI spec describes JNI class descriptors. They're
195// separated with slashes but aren't wrapped with "L;" like regular descriptors
196// (i.e. "a/b/C" rather than "La/b/C;"). Arrays of reference types are an
197// exception; there the "L;" must be present ("[La/b/C;"). Historically we've
198// supported names with dots too (such as "a.b.C").
199static std::string NormalizeJniClassDescriptor(const char* name) {
200  std::string result;
201  // Add the missing "L;" if necessary.
202  if (name[0] == '[') {
203    result = name;
204  } else {
205    result += 'L';
206    result += name;
207    result += ';';
208  }
209  // Rewrite '.' as '/' for backwards compatibility.
210  if (result.find('.') != std::string::npos) {
211    LOG(WARNING) << "Call to JNI FindClass with dots in name: "
212                 << "\"" << name << "\"";
213    std::replace(result.begin(), result.end(), '.', '/');
214  }
215  return result;
216}
217
218static void ThrowNoSuchMethodError(ScopedObjectAccess& soa, Class* c,
219                                   const char* name, const char* sig, const char* kind)
220    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
221  ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
222  soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchMethodError;",
223                                 "no %s method \"%s.%s%s\"",
224                                 kind, ClassHelper(c).GetDescriptor(), name, sig);
225}
226
227static jmethodID FindMethodID(ScopedObjectAccess& soa, jclass jni_class,
228                              const char* name, const char* sig, bool is_static)
229    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
230  Class* c = soa.Decode<Class*>(jni_class);
231  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
232    return NULL;
233  }
234
235  ArtMethod* method = NULL;
236  if (is_static) {
237    method = c->FindDirectMethod(name, sig);
238  } else {
239    method = c->FindVirtualMethod(name, sig);
240    if (method == NULL) {
241      // No virtual method matching the signature.  Search declared
242      // private methods and constructors.
243      method = c->FindDeclaredDirectMethod(name, sig);
244    }
245  }
246
247  if (method == NULL || method->IsStatic() != is_static) {
248    ThrowNoSuchMethodError(soa, c, name, sig, is_static ? "static" : "non-static");
249    return NULL;
250  }
251
252  return soa.EncodeMethod(method);
253}
254
255static ClassLoader* GetClassLoader(const ScopedObjectAccess& soa)
256    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
257  ArtMethod* method = soa.Self()->GetCurrentMethod(NULL);
258  // If we are running Runtime.nativeLoad, use the overriding ClassLoader it set.
259  if (method == soa.DecodeMethod(WellKnownClasses::java_lang_Runtime_nativeLoad)) {
260    return soa.Self()->GetClassLoaderOverride();
261  }
262  // If we have a method, use its ClassLoader for context.
263  if (method != NULL) {
264    return method->GetDeclaringClass()->GetClassLoader();
265  }
266  // We don't have a method, so try to use the system ClassLoader.
267  ClassLoader* class_loader = soa.Decode<ClassLoader*>(Runtime::Current()->GetSystemClassLoader());
268  if (class_loader != NULL) {
269    return class_loader;
270  }
271  // See if the override ClassLoader is set for gtests.
272  class_loader = soa.Self()->GetClassLoaderOverride();
273  if (class_loader != NULL) {
274    // If so, CommonTest should have set UseCompileTimeClassPath.
275    CHECK(Runtime::Current()->UseCompileTimeClassPath());
276    return class_loader;
277  }
278  // Use the BOOTCLASSPATH.
279  return NULL;
280}
281
282static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, const char* name,
283                            const char* sig, bool is_static)
284    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
285  Class* c = soa.Decode<Class*>(jni_class);
286  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
287    return NULL;
288  }
289
290  ArtField* field = NULL;
291  Class* field_type;
292  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
293  if (sig[1] != '\0') {
294    SirtRef<mirror::ClassLoader> class_loader(soa.Self(), c->GetClassLoader());
295    field_type = class_linker->FindClass(sig, class_loader.get());
296  } else {
297    field_type = class_linker->FindPrimitiveClass(*sig);
298  }
299  if (field_type == NULL) {
300    // Failed to find type from the signature of the field.
301    DCHECK(soa.Self()->IsExceptionPending());
302    ThrowLocation throw_location;
303    SirtRef<Throwable> cause(soa.Self(), soa.Self()->GetException(&throw_location));
304    soa.Self()->ClearException();
305    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
306                                   "no type \"%s\" found and so no field \"%s\" could be found in class "
307                                   "\"%s\" or its superclasses", sig, name,
308                                   ClassHelper(c).GetDescriptor());
309    soa.Self()->GetException(NULL)->SetCause(cause.get());
310    return NULL;
311  }
312  if (is_static) {
313    field = c->FindStaticField(name, ClassHelper(field_type).GetDescriptor());
314  } else {
315    field = c->FindInstanceField(name, ClassHelper(field_type).GetDescriptor());
316  }
317  if (field == NULL) {
318    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
319    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
320                                   "no \"%s\" field \"%s\" in class \"%s\" or its superclasses",
321                                   sig, name, ClassHelper(c).GetDescriptor());
322    return NULL;
323  }
324  return soa.EncodeField(field);
325}
326
327static void PinPrimitiveArray(const ScopedObjectAccess& soa, const Array* array)
328    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
329  JavaVMExt* vm = soa.Vm();
330  MutexLock mu(soa.Self(), vm->pins_lock);
331  vm->pin_table.Add(array);
332}
333
334static void UnpinPrimitiveArray(const ScopedObjectAccess& soa, const Array* array)
335    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
336  JavaVMExt* vm = soa.Vm();
337  MutexLock mu(soa.Self(), vm->pins_lock);
338  vm->pin_table.Remove(array);
339}
340
341static void ThrowAIOOBE(ScopedObjectAccess& soa, Array* array, jsize start,
342                        jsize length, const char* identifier)
343    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
344  std::string type(PrettyTypeOf(array));
345  ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
346  soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
347                                 "%s offset=%d length=%d %s.length=%d",
348                                 type.c_str(), start, length, identifier, array->GetLength());
349}
350
351static void ThrowSIOOBE(ScopedObjectAccess& soa, jsize start, jsize length,
352                        jsize array_length)
353    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
354  ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
355  soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/StringIndexOutOfBoundsException;",
356                                 "offset=%d length=%d string.length()=%d", start, length,
357                                 array_length);
358}
359
360int ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobject cause)
361    LOCKS_EXCLUDED(Locks::mutator_lock_) {
362  // Turn the const char* into a java.lang.String.
363  ScopedLocalRef<jstring> s(env, env->NewStringUTF(msg));
364  if (msg != NULL && s.get() == NULL) {
365    return JNI_ERR;
366  }
367
368  // Choose an appropriate constructor and set up the arguments.
369  jvalue args[2];
370  const char* signature;
371  if (msg == NULL && cause == NULL) {
372    signature = "()V";
373  } else if (msg != NULL && cause == NULL) {
374    signature = "(Ljava/lang/String;)V";
375    args[0].l = s.get();
376  } else if (msg == NULL && cause != NULL) {
377    signature = "(Ljava/lang/Throwable;)V";
378    args[0].l = cause;
379  } else {
380    signature = "(Ljava/lang/String;Ljava/lang/Throwable;)V";
381    args[0].l = s.get();
382    args[1].l = cause;
383  }
384  jmethodID mid = env->GetMethodID(exception_class, "<init>", signature);
385  if (mid == NULL) {
386    ScopedObjectAccess soa(env);
387    LOG(ERROR) << "No <init>" << signature << " in "
388        << PrettyClass(soa.Decode<Class*>(exception_class));
389    return JNI_ERR;
390  }
391
392  ScopedLocalRef<jthrowable> exception(env, reinterpret_cast<jthrowable>(env->NewObjectA(exception_class, mid, args)));
393  if (exception.get() == NULL) {
394    return JNI_ERR;
395  }
396  ScopedObjectAccess soa(env);
397  ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
398  soa.Self()->SetException(throw_location, soa.Decode<Throwable*>(exception.get()));
399  return JNI_OK;
400}
401
402static jint JII_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* raw_args, bool as_daemon) {
403  if (vm == NULL || p_env == NULL) {
404    return JNI_ERR;
405  }
406
407  // Return immediately if we're already attached.
408  Thread* self = Thread::Current();
409  if (self != NULL) {
410    *p_env = self->GetJniEnv();
411    return JNI_OK;
412  }
413
414  Runtime* runtime = reinterpret_cast<JavaVMExt*>(vm)->runtime;
415
416  // No threads allowed in zygote mode.
417  if (runtime->IsZygote()) {
418    LOG(ERROR) << "Attempt to attach a thread in the zygote";
419    return JNI_ERR;
420  }
421
422  JavaVMAttachArgs* args = static_cast<JavaVMAttachArgs*>(raw_args);
423  const char* thread_name = NULL;
424  jobject thread_group = NULL;
425  if (args != NULL) {
426    if (IsBadJniVersion(args->version)) {
427      LOG(ERROR) << "Bad JNI version passed to "
428                 << (as_daemon ? "AttachCurrentThreadAsDaemon" : "AttachCurrentThread") << ": "
429                 << args->version;
430      return JNI_EVERSION;
431    }
432    thread_name = args->name;
433    thread_group = args->group;
434  }
435
436  if (!runtime->AttachCurrentThread(thread_name, as_daemon, thread_group, !runtime->IsCompiler())) {
437    *p_env = NULL;
438    return JNI_ERR;
439  } else {
440    *p_env = Thread::Current()->GetJniEnv();
441    return JNI_OK;
442  }
443}
444
445class SharedLibrary {
446 public:
447  SharedLibrary(const std::string& path, void* handle, Object* class_loader)
448      : path_(path),
449        handle_(handle),
450        class_loader_(class_loader),
451        jni_on_load_lock_("JNI_OnLoad lock"),
452        jni_on_load_cond_("JNI_OnLoad condition variable", jni_on_load_lock_),
453        jni_on_load_thread_id_(Thread::Current()->GetThinLockId()),
454        jni_on_load_result_(kPending) {
455  }
456
457  Object* GetClassLoader() {
458    return class_loader_;
459  }
460
461  std::string GetPath() {
462    return path_;
463  }
464
465  /*
466   * Check the result of an earlier call to JNI_OnLoad on this library.
467   * If the call has not yet finished in another thread, wait for it.
468   */
469  bool CheckOnLoadResult()
470      LOCKS_EXCLUDED(jni_on_load_lock_)
471      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
472    Thread* self = Thread::Current();
473    self->TransitionFromRunnableToSuspended(kWaitingForJniOnLoad);
474    bool okay;
475    {
476      MutexLock mu(self, jni_on_load_lock_);
477
478      if (jni_on_load_thread_id_ == self->GetThinLockId()) {
479        // Check this so we don't end up waiting for ourselves.  We need to return "true" so the
480        // caller can continue.
481        LOG(INFO) << *self << " recursive attempt to load library " << "\"" << path_ << "\"";
482        okay = true;
483      } else {
484        while (jni_on_load_result_ == kPending) {
485          VLOG(jni) << "[" << *self << " waiting for \"" << path_ << "\" " << "JNI_OnLoad...]";
486          jni_on_load_cond_.Wait(self);
487        }
488
489        okay = (jni_on_load_result_ == kOkay);
490        VLOG(jni) << "[Earlier JNI_OnLoad for \"" << path_ << "\" "
491            << (okay ? "succeeded" : "failed") << "]";
492      }
493    }
494    self->TransitionFromSuspendedToRunnable();
495    return okay;
496  }
497
498  void SetResult(bool result) LOCKS_EXCLUDED(jni_on_load_lock_) {
499    Thread* self = Thread::Current();
500    MutexLock mu(self, jni_on_load_lock_);
501
502    jni_on_load_result_ = result ? kOkay : kFailed;
503    jni_on_load_thread_id_ = 0;
504
505    // Broadcast a wakeup to anybody sleeping on the condition variable.
506    jni_on_load_cond_.Broadcast(self);
507  }
508
509  void* FindSymbol(const std::string& symbol_name) {
510    return dlsym(handle_, symbol_name.c_str());
511  }
512
513 private:
514  enum JNI_OnLoadState {
515    kPending,
516    kFailed,
517    kOkay,
518  };
519
520  // Path to library "/system/lib/libjni.so".
521  std::string path_;
522
523  // The void* returned by dlopen(3).
524  void* handle_;
525
526  // The ClassLoader this library is associated with.
527  Object* class_loader_;
528
529  // Guards remaining items.
530  Mutex jni_on_load_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
531  // Wait for JNI_OnLoad in other thread.
532  ConditionVariable jni_on_load_cond_ GUARDED_BY(jni_on_load_lock_);
533  // Recursive invocation guard.
534  uint32_t jni_on_load_thread_id_ GUARDED_BY(jni_on_load_lock_);
535  // Result of earlier JNI_OnLoad call.
536  JNI_OnLoadState jni_on_load_result_ GUARDED_BY(jni_on_load_lock_);
537};
538
539// This exists mainly to keep implementation details out of the header file.
540class Libraries {
541 public:
542  Libraries() {
543  }
544
545  ~Libraries() {
546    STLDeleteValues(&libraries_);
547  }
548
549  void Dump(std::ostream& os) const {
550    bool first = true;
551    for (const auto& library : libraries_) {
552      if (!first) {
553        os << ' ';
554      }
555      first = false;
556      os << library.first;
557    }
558  }
559
560  size_t size() const {
561    return libraries_.size();
562  }
563
564  SharedLibrary* Get(const std::string& path) {
565    auto it = libraries_.find(path);
566    return (it == libraries_.end()) ? NULL : it->second;
567  }
568
569  void Put(const std::string& path, SharedLibrary* library) {
570    libraries_.Put(path, library);
571  }
572
573  // See section 11.3 "Linking Native Methods" of the JNI spec.
574  void* FindNativeMethod(const ArtMethod* m, std::string& detail)
575      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
576    std::string jni_short_name(JniShortName(m));
577    std::string jni_long_name(JniLongName(m));
578    const ClassLoader* declaring_class_loader = m->GetDeclaringClass()->GetClassLoader();
579    for (const auto& lib : libraries_) {
580      SharedLibrary* library = lib.second;
581      if (library->GetClassLoader() != declaring_class_loader) {
582        // We only search libraries loaded by the appropriate ClassLoader.
583        continue;
584      }
585      // Try the short name then the long name...
586      void* fn = library->FindSymbol(jni_short_name);
587      if (fn == NULL) {
588        fn = library->FindSymbol(jni_long_name);
589      }
590      if (fn != NULL) {
591        VLOG(jni) << "[Found native code for " << PrettyMethod(m)
592                  << " in \"" << library->GetPath() << "\"]";
593        return fn;
594      }
595    }
596    detail += "No implementation found for ";
597    detail += PrettyMethod(m);
598    detail += " (tried " + jni_short_name + " and " + jni_long_name + ")";
599    LOG(ERROR) << detail;
600    return NULL;
601  }
602
603 private:
604  SafeMap<std::string, SharedLibrary*> libraries_;
605};
606
607JValue InvokeWithJValues(const ScopedObjectAccess& soa, jobject obj, jmethodID mid,
608                         jvalue* args) {
609  ArtMethod* method = soa.DecodeMethod(mid);
610  Object* receiver = method->IsStatic() ? NULL : soa.Decode<Object*>(obj);
611  MethodHelper mh(method);
612  JValue result;
613  ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
614  arg_array.BuildArgArray(soa, receiver, args);
615  InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()[0]);
616  return result;
617}
618
619#define CHECK_NON_NULL_ARGUMENT(fn, value) \
620  if (UNLIKELY(value == NULL)) { \
621    JniAbortF(#fn, #value " == null"); \
622  }
623
624#define CHECK_NON_NULL_MEMCPY_ARGUMENT(fn, length, value) \
625  if (UNLIKELY(length != 0 && value == NULL)) { \
626    JniAbortF(#fn, #value " == null"); \
627  }
628
629class JNI {
630 public:
631  static jint GetVersion(JNIEnv*) {
632    return JNI_VERSION_1_6;
633  }
634
635  static jclass DefineClass(JNIEnv*, const char*, jobject, const jbyte*, jsize) {
636    LOG(WARNING) << "JNI DefineClass is not supported";
637    return NULL;
638  }
639
640  static jclass FindClass(JNIEnv* env, const char* name) {
641    CHECK_NON_NULL_ARGUMENT(FindClass, name);
642    Runtime* runtime = Runtime::Current();
643    ClassLinker* class_linker = runtime->GetClassLinker();
644    std::string descriptor(NormalizeJniClassDescriptor(name));
645    ScopedObjectAccess soa(env);
646    Class* c = NULL;
647    if (runtime->IsStarted()) {
648      ClassLoader* cl = GetClassLoader(soa);
649      c = class_linker->FindClass(descriptor.c_str(), cl);
650    } else {
651      c = class_linker->FindSystemClass(descriptor.c_str());
652    }
653    return soa.AddLocalReference<jclass>(c);
654  }
655
656  static jmethodID FromReflectedMethod(JNIEnv* env, jobject java_method) {
657    CHECK_NON_NULL_ARGUMENT(FromReflectedMethod, java_method);
658    ScopedObjectAccess soa(env);
659    jobject art_method = env->GetObjectField(java_method,
660                                             WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
661    ArtMethod* method = soa.Decode<ArtMethod*>(art_method);
662    DCHECK(method != NULL);
663    return soa.EncodeMethod(method);
664  }
665
666  static jfieldID FromReflectedField(JNIEnv* env, jobject java_field) {
667    CHECK_NON_NULL_ARGUMENT(FromReflectedField, java_field);
668    ScopedObjectAccess soa(env);
669    jobject art_field = env->GetObjectField(java_field,
670                                            WellKnownClasses::java_lang_reflect_Field_artField);
671    ArtField* field = soa.Decode<ArtField*>(art_field);
672    DCHECK(field != NULL);
673    return soa.EncodeField(field);
674  }
675
676  static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
677    CHECK_NON_NULL_ARGUMENT(ToReflectedMethod, mid);
678    ScopedObjectAccess soa(env);
679    ArtMethod* m = soa.DecodeMethod(mid);
680    jobject art_method = soa.AddLocalReference<jobject>(m);
681    jobject reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Method);
682    if (env->ExceptionCheck()) {
683      return NULL;
684    }
685    SetObjectField(env,
686                   reflect_method,
687                   WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod,
688                   art_method);
689    return reflect_method;
690  }
691
692  static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) {
693    CHECK_NON_NULL_ARGUMENT(ToReflectedField, fid);
694    ScopedObjectAccess soa(env);
695    ArtField* f = soa.DecodeField(fid);
696    jobject art_field = soa.AddLocalReference<jobject>(f);
697    jobject reflect_field = env->AllocObject(WellKnownClasses::java_lang_reflect_Field);
698    if (env->ExceptionCheck()) {
699      return NULL;
700    }
701    SetObjectField(env,
702                   reflect_field,
703                   WellKnownClasses::java_lang_reflect_Field_artField,
704                   art_field);
705    return reflect_field;
706  }
707
708  static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
709    CHECK_NON_NULL_ARGUMENT(GetObjectClass, java_object);
710    ScopedObjectAccess soa(env);
711    Object* o = soa.Decode<Object*>(java_object);
712    return soa.AddLocalReference<jclass>(o->GetClass());
713  }
714
715  static jclass GetSuperclass(JNIEnv* env, jclass java_class) {
716    CHECK_NON_NULL_ARGUMENT(GetSuperclass, java_class);
717    ScopedObjectAccess soa(env);
718    Class* c = soa.Decode<Class*>(java_class);
719    return soa.AddLocalReference<jclass>(c->GetSuperClass());
720  }
721
722  static jboolean IsAssignableFrom(JNIEnv* env, jclass java_class1, jclass java_class2) {
723    CHECK_NON_NULL_ARGUMENT(IsAssignableFrom, java_class1);
724    CHECK_NON_NULL_ARGUMENT(IsAssignableFrom, java_class2);
725    ScopedObjectAccess soa(env);
726    Class* c1 = soa.Decode<Class*>(java_class1);
727    Class* c2 = soa.Decode<Class*>(java_class2);
728    return c1->IsAssignableFrom(c2) ? JNI_TRUE : JNI_FALSE;
729  }
730
731  static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass java_class) {
732    CHECK_NON_NULL_ARGUMENT(IsInstanceOf, java_class);
733    if (jobj == NULL) {
734      // Note: JNI is different from regular Java instanceof in this respect
735      return JNI_TRUE;
736    } else {
737      ScopedObjectAccess soa(env);
738      Object* obj = soa.Decode<Object*>(jobj);
739      Class* c = soa.Decode<Class*>(java_class);
740      return obj->InstanceOf(c) ? JNI_TRUE : JNI_FALSE;
741    }
742  }
743
744  static jint Throw(JNIEnv* env, jthrowable java_exception) {
745    ScopedObjectAccess soa(env);
746    Throwable* exception = soa.Decode<Throwable*>(java_exception);
747    if (exception == NULL) {
748      return JNI_ERR;
749    }
750    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
751    soa.Self()->SetException(throw_location, exception);
752    return JNI_OK;
753  }
754
755  static jint ThrowNew(JNIEnv* env, jclass c, const char* msg) {
756    CHECK_NON_NULL_ARGUMENT(ThrowNew, c);
757    return ThrowNewException(env, c, msg, NULL);
758  }
759
760  static jboolean ExceptionCheck(JNIEnv* env) {
761    return static_cast<JNIEnvExt*>(env)->self->IsExceptionPending() ? JNI_TRUE : JNI_FALSE;
762  }
763
764  static void ExceptionClear(JNIEnv* env) {
765    static_cast<JNIEnvExt*>(env)->self->ClearException();
766  }
767
768  static void ExceptionDescribe(JNIEnv* env) {
769    ScopedObjectAccess soa(env);
770
771    SirtRef<Object> old_throw_this_object(soa.Self(), NULL);
772    SirtRef<ArtMethod> old_throw_method(soa.Self(), NULL);
773    SirtRef<Throwable> old_exception(soa.Self(), NULL);
774    uint32_t old_throw_dex_pc;
775    {
776      ThrowLocation old_throw_location;
777      Throwable* old_exception_obj = soa.Self()->GetException(&old_throw_location);
778      old_throw_this_object.reset(old_throw_location.GetThis());
779      old_throw_method.reset(old_throw_location.GetMethod());
780      old_exception.reset(old_exception_obj);
781      old_throw_dex_pc = old_throw_location.GetDexPc();
782      soa.Self()->ClearException();
783    }
784    ScopedLocalRef<jthrowable> exception(env, soa.AddLocalReference<jthrowable>(old_exception.get()));
785    ScopedLocalRef<jclass> exception_class(env, env->GetObjectClass(exception.get()));
786    jmethodID mid = env->GetMethodID(exception_class.get(), "printStackTrace", "()V");
787    if (mid == NULL) {
788      LOG(WARNING) << "JNI WARNING: no printStackTrace()V in "
789                   << PrettyTypeOf(old_exception.get());
790    } else {
791      env->CallVoidMethod(exception.get(), mid);
792      if (soa.Self()->IsExceptionPending()) {
793        LOG(WARNING) << "JNI WARNING: " << PrettyTypeOf(soa.Self()->GetException(NULL))
794                     << " thrown while calling printStackTrace";
795        soa.Self()->ClearException();
796      }
797    }
798    ThrowLocation gc_safe_throw_location(old_throw_this_object.get(), old_throw_method.get(),
799                                         old_throw_dex_pc);
800
801    soa.Self()->SetException(gc_safe_throw_location, old_exception.get());
802  }
803
804  static jthrowable ExceptionOccurred(JNIEnv* env) {
805    ScopedObjectAccess soa(env);
806    Object* exception = soa.Self()->GetException(NULL);
807    return soa.AddLocalReference<jthrowable>(exception);
808  }
809
810  static void FatalError(JNIEnv*, const char* msg) {
811    LOG(FATAL) << "JNI FatalError called: " << msg;
812  }
813
814  static jint PushLocalFrame(JNIEnv* env, jint capacity) {
815    if (EnsureLocalCapacity(env, capacity, "PushLocalFrame") != JNI_OK) {
816      return JNI_ERR;
817    }
818    static_cast<JNIEnvExt*>(env)->PushFrame(capacity);
819    return JNI_OK;
820  }
821
822  static jobject PopLocalFrame(JNIEnv* env, jobject java_survivor) {
823    ScopedObjectAccess soa(env);
824    Object* survivor = soa.Decode<Object*>(java_survivor);
825    soa.Env()->PopFrame();
826    return soa.AddLocalReference<jobject>(survivor);
827  }
828
829  static jint EnsureLocalCapacity(JNIEnv* env, jint desired_capacity) {
830    return EnsureLocalCapacity(env, desired_capacity, "EnsureLocalCapacity");
831  }
832
833  static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
834    ScopedObjectAccess soa(env);
835    Object* decoded_obj = soa.Decode<Object*>(obj);
836    // Check for null after decoding the object to handle cleared weak globals.
837    if (decoded_obj == nullptr) {
838      return nullptr;
839    }
840    JavaVMExt* vm = soa.Vm();
841    IndirectReferenceTable& globals = vm->globals;
842    WriterMutexLock mu(soa.Self(), vm->globals_lock);
843    IndirectRef ref = globals.Add(IRT_FIRST_SEGMENT, decoded_obj);
844    return reinterpret_cast<jobject>(ref);
845  }
846
847  static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
848    if (obj == NULL) {
849      return;
850    }
851    JavaVMExt* vm = reinterpret_cast<JNIEnvExt*>(env)->vm;
852    IndirectReferenceTable& globals = vm->globals;
853    Thread* self = reinterpret_cast<JNIEnvExt*>(env)->self;
854    WriterMutexLock mu(self, vm->globals_lock);
855
856    if (!globals.Remove(IRT_FIRST_SEGMENT, obj)) {
857      LOG(WARNING) << "JNI WARNING: DeleteGlobalRef(" << obj << ") "
858                   << "failed to find entry";
859    }
860  }
861
862  static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
863    ScopedObjectAccess soa(env);
864    return AddWeakGlobalReference(soa, soa.Decode<Object*>(obj));
865  }
866
867  static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
868    if (obj != nullptr) {
869      ScopedObjectAccess soa(env);
870      soa.Vm()->DeleteWeakGlobalRef(soa.Self(), obj);
871    }
872  }
873
874  static jobject NewLocalRef(JNIEnv* env, jobject obj) {
875    ScopedObjectAccess soa(env);
876    mirror::Object* decoded_obj = soa.Decode<Object*>(obj);
877    // Check for null after decoding the object to handle cleared weak globals.
878    if (decoded_obj == nullptr) {
879      return nullptr;
880    }
881    return soa.AddLocalReference<jobject>(decoded_obj);
882  }
883
884  static void DeleteLocalRef(JNIEnv* env, jobject obj) {
885    if (obj == NULL) {
886      return;
887    }
888    IndirectReferenceTable& locals = reinterpret_cast<JNIEnvExt*>(env)->locals;
889
890    uint32_t cookie = reinterpret_cast<JNIEnvExt*>(env)->local_ref_cookie;
891    if (!locals.Remove(cookie, obj)) {
892      // Attempting to delete a local reference that is not in the
893      // topmost local reference frame is a no-op.  DeleteLocalRef returns
894      // void and doesn't throw any exceptions, but we should probably
895      // complain about it so the user will notice that things aren't
896      // going quite the way they expect.
897      LOG(WARNING) << "JNI WARNING: DeleteLocalRef(" << obj << ") "
898                   << "failed to find entry";
899    }
900  }
901
902  static jboolean IsSameObject(JNIEnv* env, jobject obj1, jobject obj2) {
903    if (obj1 == obj2) {
904      return JNI_TRUE;
905    } else {
906      ScopedObjectAccess soa(env);
907      return (soa.Decode<Object*>(obj1) == soa.Decode<Object*>(obj2)) ? JNI_TRUE : JNI_FALSE;
908    }
909  }
910
911  static jobject AllocObject(JNIEnv* env, jclass java_class) {
912    CHECK_NON_NULL_ARGUMENT(AllocObject, java_class);
913    ScopedObjectAccess soa(env);
914    Class* c = soa.Decode<Class*>(java_class);
915    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
916      return NULL;
917    }
918    return soa.AddLocalReference<jobject>(c->AllocObject(soa.Self()));
919  }
920
921  static jobject NewObject(JNIEnv* env, jclass java_class, jmethodID mid, ...) {
922    va_list args;
923    va_start(args, mid);
924    CHECK_NON_NULL_ARGUMENT(NewObject, java_class);
925    CHECK_NON_NULL_ARGUMENT(NewObject, mid);
926    jobject result = NewObjectV(env, java_class, mid, args);
927    va_end(args);
928    return result;
929  }
930
931  static jobject NewObjectV(JNIEnv* env, jclass java_class, jmethodID mid, va_list args) {
932    CHECK_NON_NULL_ARGUMENT(NewObjectV, java_class);
933    CHECK_NON_NULL_ARGUMENT(NewObjectV, mid);
934    ScopedObjectAccess soa(env);
935    Class* c = soa.Decode<Class*>(java_class);
936    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
937      return NULL;
938    }
939    Object* result = c->AllocObject(soa.Self());
940    if (result == NULL) {
941      return NULL;
942    }
943    jobject local_result = soa.AddLocalReference<jobject>(result);
944    CallNonvirtualVoidMethodV(env, local_result, java_class, mid, args);
945    if (!soa.Self()->IsExceptionPending()) {
946      return local_result;
947    } else {
948      return NULL;
949    }
950  }
951
952  static jobject NewObjectA(JNIEnv* env, jclass java_class, jmethodID mid, jvalue* args) {
953    CHECK_NON_NULL_ARGUMENT(NewObjectA, java_class);
954    CHECK_NON_NULL_ARGUMENT(NewObjectA, mid);
955    ScopedObjectAccess soa(env);
956    Class* c = soa.Decode<Class*>(java_class);
957    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
958      return NULL;
959    }
960    Object* result = c->AllocObject(soa.Self());
961    if (result == NULL) {
962      return NULL;
963    }
964    jobject local_result = soa.AddLocalReference<jobjectArray>(result);
965    CallNonvirtualVoidMethodA(env, local_result, java_class, mid, args);
966    if (!soa.Self()->IsExceptionPending()) {
967      return local_result;
968    } else {
969      return NULL;
970    }
971  }
972
973  static jmethodID GetMethodID(JNIEnv* env, jclass java_class, const char* name, const char* sig) {
974    CHECK_NON_NULL_ARGUMENT(GetMethodID, java_class);
975    CHECK_NON_NULL_ARGUMENT(GetMethodID, name);
976    CHECK_NON_NULL_ARGUMENT(GetMethodID, sig);
977    ScopedObjectAccess soa(env);
978    return FindMethodID(soa, java_class, name, sig, false);
979  }
980
981  static jmethodID GetStaticMethodID(JNIEnv* env, jclass java_class, const char* name,
982                                     const char* sig) {
983    CHECK_NON_NULL_ARGUMENT(GetStaticMethodID, java_class);
984    CHECK_NON_NULL_ARGUMENT(GetStaticMethodID, name);
985    CHECK_NON_NULL_ARGUMENT(GetStaticMethodID, sig);
986    ScopedObjectAccess soa(env);
987    return FindMethodID(soa, java_class, name, sig, true);
988  }
989
990  static jobject CallObjectMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
991    va_list ap;
992    va_start(ap, mid);
993    CHECK_NON_NULL_ARGUMENT(CallObjectMethod, obj);
994    CHECK_NON_NULL_ARGUMENT(CallObjectMethod, mid);
995    ScopedObjectAccess soa(env);
996    JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
997    va_end(ap);
998    return soa.AddLocalReference<jobject>(result.GetL());
999  }
1000
1001  static jobject CallObjectMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
1002    CHECK_NON_NULL_ARGUMENT(CallObjectMethodV, obj);
1003    CHECK_NON_NULL_ARGUMENT(CallObjectMethodV, mid);
1004    ScopedObjectAccess soa(env);
1005    JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args));
1006    return soa.AddLocalReference<jobject>(result.GetL());
1007  }
1008
1009  static jobject CallObjectMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
1010    CHECK_NON_NULL_ARGUMENT(CallObjectMethodA, obj);
1011    CHECK_NON_NULL_ARGUMENT(CallObjectMethodA, mid);
1012    ScopedObjectAccess soa(env);
1013    JValue result(InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args));
1014    return soa.AddLocalReference<jobject>(result.GetL());
1015  }
1016
1017  static jboolean CallBooleanMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1018    va_list ap;
1019    va_start(ap, mid);
1020    CHECK_NON_NULL_ARGUMENT(CallBooleanMethod, obj);
1021    CHECK_NON_NULL_ARGUMENT(CallBooleanMethod, mid);
1022    ScopedObjectAccess soa(env);
1023    JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
1024    va_end(ap);
1025    return result.GetZ();
1026  }
1027
1028  static jboolean CallBooleanMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
1029    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodV, obj);
1030    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodV, mid);
1031    ScopedObjectAccess soa(env);
1032    return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetZ();
1033  }
1034
1035  static jboolean CallBooleanMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
1036    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodA, obj);
1037    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodA, mid);
1038    ScopedObjectAccess soa(env);
1039    return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetZ();
1040  }
1041
1042  static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1043    va_list ap;
1044    va_start(ap, mid);
1045    CHECK_NON_NULL_ARGUMENT(CallByteMethod, obj);
1046    CHECK_NON_NULL_ARGUMENT(CallByteMethod, mid);
1047    ScopedObjectAccess soa(env);
1048    JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
1049    va_end(ap);
1050    return result.GetB();
1051  }
1052
1053  static jbyte CallByteMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
1054    CHECK_NON_NULL_ARGUMENT(CallByteMethodV, obj);
1055    CHECK_NON_NULL_ARGUMENT(CallByteMethodV, mid);
1056    ScopedObjectAccess soa(env);
1057    return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetB();
1058  }
1059
1060  static jbyte CallByteMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
1061    CHECK_NON_NULL_ARGUMENT(CallByteMethodA, obj);
1062    CHECK_NON_NULL_ARGUMENT(CallByteMethodA, mid);
1063    ScopedObjectAccess soa(env);
1064    return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetB();
1065  }
1066
1067  static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1068    va_list ap;
1069    va_start(ap, mid);
1070    CHECK_NON_NULL_ARGUMENT(CallCharMethod, obj);
1071    CHECK_NON_NULL_ARGUMENT(CallCharMethod, mid);
1072    ScopedObjectAccess soa(env);
1073    JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
1074    va_end(ap);
1075    return result.GetC();
1076  }
1077
1078  static jchar CallCharMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
1079    CHECK_NON_NULL_ARGUMENT(CallCharMethodV, obj);
1080    CHECK_NON_NULL_ARGUMENT(CallCharMethodV, mid);
1081    ScopedObjectAccess soa(env);
1082    return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetC();
1083  }
1084
1085  static jchar CallCharMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
1086    CHECK_NON_NULL_ARGUMENT(CallCharMethodA, obj);
1087    CHECK_NON_NULL_ARGUMENT(CallCharMethodA, mid);
1088    ScopedObjectAccess soa(env);
1089    return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetC();
1090  }
1091
1092  static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1093    va_list ap;
1094    va_start(ap, mid);
1095    CHECK_NON_NULL_ARGUMENT(CallDoubleMethod, obj);
1096    CHECK_NON_NULL_ARGUMENT(CallDoubleMethod, mid);
1097    ScopedObjectAccess soa(env);
1098    JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
1099    va_end(ap);
1100    return result.GetD();
1101  }
1102
1103  static jdouble CallDoubleMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
1104    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodV, obj);
1105    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodV, mid);
1106    ScopedObjectAccess soa(env);
1107    return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetD();
1108  }
1109
1110  static jdouble CallDoubleMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
1111    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodA, obj);
1112    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodA, mid);
1113    ScopedObjectAccess soa(env);
1114    return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetD();
1115  }
1116
1117  static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1118    va_list ap;
1119    va_start(ap, mid);
1120    CHECK_NON_NULL_ARGUMENT(CallFloatMethod, obj);
1121    CHECK_NON_NULL_ARGUMENT(CallFloatMethod, mid);
1122    ScopedObjectAccess soa(env);
1123    JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
1124    va_end(ap);
1125    return result.GetF();
1126  }
1127
1128  static jfloat CallFloatMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
1129    CHECK_NON_NULL_ARGUMENT(CallFloatMethodV, obj);
1130    CHECK_NON_NULL_ARGUMENT(CallFloatMethodV, mid);
1131    ScopedObjectAccess soa(env);
1132    return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetF();
1133  }
1134
1135  static jfloat CallFloatMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
1136    CHECK_NON_NULL_ARGUMENT(CallFloatMethodA, obj);
1137    CHECK_NON_NULL_ARGUMENT(CallFloatMethodA, mid);
1138    ScopedObjectAccess soa(env);
1139    return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetF();
1140  }
1141
1142  static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1143    va_list ap;
1144    va_start(ap, mid);
1145    CHECK_NON_NULL_ARGUMENT(CallIntMethod, obj);
1146    CHECK_NON_NULL_ARGUMENT(CallIntMethod, mid);
1147    ScopedObjectAccess soa(env);
1148    JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
1149    va_end(ap);
1150    return result.GetI();
1151  }
1152
1153  static jint CallIntMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
1154    CHECK_NON_NULL_ARGUMENT(CallIntMethodV, obj);
1155    CHECK_NON_NULL_ARGUMENT(CallIntMethodV, mid);
1156    ScopedObjectAccess soa(env);
1157    return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetI();
1158  }
1159
1160  static jint CallIntMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
1161    CHECK_NON_NULL_ARGUMENT(CallIntMethodA, obj);
1162    CHECK_NON_NULL_ARGUMENT(CallIntMethodA, mid);
1163    ScopedObjectAccess soa(env);
1164    return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetI();
1165  }
1166
1167  static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1168    va_list ap;
1169    va_start(ap, mid);
1170    CHECK_NON_NULL_ARGUMENT(CallLongMethod, obj);
1171    CHECK_NON_NULL_ARGUMENT(CallLongMethod, mid);
1172    ScopedObjectAccess soa(env);
1173    JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
1174    va_end(ap);
1175    return result.GetJ();
1176  }
1177
1178  static jlong CallLongMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
1179    CHECK_NON_NULL_ARGUMENT(CallLongMethodV, obj);
1180    CHECK_NON_NULL_ARGUMENT(CallLongMethodV, mid);
1181    ScopedObjectAccess soa(env);
1182    return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetJ();
1183  }
1184
1185  static jlong CallLongMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
1186    CHECK_NON_NULL_ARGUMENT(CallLongMethodA, obj);
1187    CHECK_NON_NULL_ARGUMENT(CallLongMethodA, mid);
1188    ScopedObjectAccess soa(env);
1189    return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetJ();
1190  }
1191
1192  static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1193    va_list ap;
1194    va_start(ap, mid);
1195    CHECK_NON_NULL_ARGUMENT(CallShortMethod, obj);
1196    CHECK_NON_NULL_ARGUMENT(CallShortMethod, mid);
1197    ScopedObjectAccess soa(env);
1198    JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
1199    va_end(ap);
1200    return result.GetS();
1201  }
1202
1203  static jshort CallShortMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
1204    CHECK_NON_NULL_ARGUMENT(CallShortMethodV, obj);
1205    CHECK_NON_NULL_ARGUMENT(CallShortMethodV, mid);
1206    ScopedObjectAccess soa(env);
1207    return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetS();
1208  }
1209
1210  static jshort CallShortMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
1211    CHECK_NON_NULL_ARGUMENT(CallShortMethodA, obj);
1212    CHECK_NON_NULL_ARGUMENT(CallShortMethodA, mid);
1213    ScopedObjectAccess soa(env);
1214    return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetS();
1215  }
1216
1217  static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
1218    va_list ap;
1219    va_start(ap, mid);
1220    CHECK_NON_NULL_ARGUMENT(CallVoidMethod, obj);
1221    CHECK_NON_NULL_ARGUMENT(CallVoidMethod, mid);
1222    ScopedObjectAccess soa(env);
1223    InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap);
1224    va_end(ap);
1225  }
1226
1227  static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
1228    CHECK_NON_NULL_ARGUMENT(CallVoidMethodV, obj);
1229    CHECK_NON_NULL_ARGUMENT(CallVoidMethodV, mid);
1230    ScopedObjectAccess soa(env);
1231    InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args);
1232  }
1233
1234  static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
1235    CHECK_NON_NULL_ARGUMENT(CallVoidMethodA, obj);
1236    CHECK_NON_NULL_ARGUMENT(CallVoidMethodA, mid);
1237    ScopedObjectAccess soa(env);
1238    InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args);
1239  }
1240
1241  static jobject CallNonvirtualObjectMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
1242    va_list ap;
1243    va_start(ap, mid);
1244    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethod, obj);
1245    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethod, mid);
1246    ScopedObjectAccess soa(env);
1247    JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
1248    jobject local_result = soa.AddLocalReference<jobject>(result.GetL());
1249    va_end(ap);
1250    return local_result;
1251  }
1252
1253  static jobject CallNonvirtualObjectMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1254                                             va_list args) {
1255    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodV, obj);
1256    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodV, mid);
1257    ScopedObjectAccess soa(env);
1258    JValue result(InvokeWithVarArgs(soa, obj, mid, args));
1259    return soa.AddLocalReference<jobject>(result.GetL());
1260  }
1261
1262  static jobject CallNonvirtualObjectMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1263                                             jvalue* args) {
1264    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodA, obj);
1265    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodA, mid);
1266    ScopedObjectAccess soa(env);
1267    JValue result(InvokeWithJValues(soa, obj, mid, args));
1268    return soa.AddLocalReference<jobject>(result.GetL());
1269  }
1270
1271  static jboolean CallNonvirtualBooleanMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1272                                              ...) {
1273    va_list ap;
1274    va_start(ap, mid);
1275    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethod, obj);
1276    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethod, mid);
1277    ScopedObjectAccess soa(env);
1278    JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
1279    va_end(ap);
1280    return result.GetZ();
1281  }
1282
1283  static jboolean CallNonvirtualBooleanMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1284                                               va_list args) {
1285    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodV, obj);
1286    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodV, mid);
1287    ScopedObjectAccess soa(env);
1288    return InvokeWithVarArgs(soa, obj, mid, args).GetZ();
1289  }
1290
1291  static jboolean CallNonvirtualBooleanMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1292                                               jvalue* args) {
1293    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodA, obj);
1294    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodA, mid);
1295    ScopedObjectAccess soa(env);
1296    return InvokeWithJValues(soa, obj, mid, args).GetZ();
1297  }
1298
1299  static jbyte CallNonvirtualByteMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
1300    va_list ap;
1301    va_start(ap, mid);
1302    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethod, obj);
1303    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethod, mid);
1304    ScopedObjectAccess soa(env);
1305    JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
1306    va_end(ap);
1307    return result.GetB();
1308  }
1309
1310  static jbyte CallNonvirtualByteMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1311                                         va_list args) {
1312    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodV, obj);
1313    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodV, mid);
1314    ScopedObjectAccess soa(env);
1315    return InvokeWithVarArgs(soa, obj, mid, args).GetB();
1316  }
1317
1318  static jbyte CallNonvirtualByteMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1319                                         jvalue* args) {
1320    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodA, obj);
1321    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodA, mid);
1322    ScopedObjectAccess soa(env);
1323    return InvokeWithJValues(soa, obj, mid, args).GetB();
1324  }
1325
1326  static jchar CallNonvirtualCharMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
1327    va_list ap;
1328    va_start(ap, mid);
1329    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethod, obj);
1330    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethod, mid);
1331    ScopedObjectAccess soa(env);
1332    JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
1333    va_end(ap);
1334    return result.GetC();
1335  }
1336
1337  static jchar CallNonvirtualCharMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1338                                         va_list args) {
1339    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodV, obj);
1340    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodV, mid);
1341    ScopedObjectAccess soa(env);
1342    return InvokeWithVarArgs(soa, obj, mid, args).GetC();
1343  }
1344
1345  static jchar CallNonvirtualCharMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1346                                         jvalue* args) {
1347    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodA, obj);
1348    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodA, mid);
1349    ScopedObjectAccess soa(env);
1350    return InvokeWithJValues(soa, obj, mid, args).GetC();
1351  }
1352
1353  static jshort CallNonvirtualShortMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
1354    va_list ap;
1355    va_start(ap, mid);
1356    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethod, obj);
1357    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethod, mid);
1358    ScopedObjectAccess soa(env);
1359    JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
1360    va_end(ap);
1361    return result.GetS();
1362  }
1363
1364  static jshort CallNonvirtualShortMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1365                                           va_list args) {
1366    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodV, obj);
1367    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodV, mid);
1368    ScopedObjectAccess soa(env);
1369    return InvokeWithVarArgs(soa, obj, mid, args).GetS();
1370  }
1371
1372  static jshort CallNonvirtualShortMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1373                                           jvalue* args) {
1374    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodA, obj);
1375    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodA, mid);
1376    ScopedObjectAccess soa(env);
1377    return InvokeWithJValues(soa, obj, mid, args).GetS();
1378  }
1379
1380  static jint CallNonvirtualIntMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
1381    va_list ap;
1382    va_start(ap, mid);
1383    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethod, obj);
1384    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethod, mid);
1385    ScopedObjectAccess soa(env);
1386    JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
1387    va_end(ap);
1388    return result.GetI();
1389  }
1390
1391  static jint CallNonvirtualIntMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1392                                       va_list args) {
1393    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodV, obj);
1394    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodV, mid);
1395    ScopedObjectAccess soa(env);
1396    return InvokeWithVarArgs(soa, obj, mid, args).GetI();
1397  }
1398
1399  static jint CallNonvirtualIntMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1400                                       jvalue* args) {
1401    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodA, obj);
1402    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodA, mid);
1403    ScopedObjectAccess soa(env);
1404    return InvokeWithJValues(soa, obj, mid, args).GetI();
1405  }
1406
1407  static jlong CallNonvirtualLongMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
1408    va_list ap;
1409    va_start(ap, mid);
1410    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethod, obj);
1411    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethod, mid);
1412    ScopedObjectAccess soa(env);
1413    JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
1414    va_end(ap);
1415    return result.GetJ();
1416  }
1417
1418  static jlong CallNonvirtualLongMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1419                                         va_list args) {
1420    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodV, obj);
1421    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodV, mid);
1422    ScopedObjectAccess soa(env);
1423    return InvokeWithVarArgs(soa, obj, mid, args).GetJ();
1424  }
1425
1426  static jlong CallNonvirtualLongMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1427                                         jvalue* args) {
1428    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodA, obj);
1429    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodA, mid);
1430    ScopedObjectAccess soa(env);
1431    return InvokeWithJValues(soa, obj, mid, args).GetJ();
1432  }
1433
1434  static jfloat CallNonvirtualFloatMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
1435    va_list ap;
1436    va_start(ap, mid);
1437    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethod, obj);
1438    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethod, mid);
1439    ScopedObjectAccess soa(env);
1440    JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
1441    va_end(ap);
1442    return result.GetF();
1443  }
1444
1445  static jfloat CallNonvirtualFloatMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1446                                           va_list args) {
1447    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodV, obj);
1448    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodV, mid);
1449    ScopedObjectAccess soa(env);
1450    return InvokeWithVarArgs(soa, obj, mid, args).GetF();
1451  }
1452
1453  static jfloat CallNonvirtualFloatMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1454                                           jvalue* args) {
1455    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodA, obj);
1456    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodA, mid);
1457    ScopedObjectAccess soa(env);
1458    return InvokeWithJValues(soa, obj, mid, args).GetF();
1459  }
1460
1461  static jdouble CallNonvirtualDoubleMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
1462    va_list ap;
1463    va_start(ap, mid);
1464    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethod, obj);
1465    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethod, mid);
1466    ScopedObjectAccess soa(env);
1467    JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
1468    va_end(ap);
1469    return result.GetD();
1470  }
1471
1472  static jdouble CallNonvirtualDoubleMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1473                                             va_list args) {
1474    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodV, obj);
1475    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodV, mid);
1476    ScopedObjectAccess soa(env);
1477    return InvokeWithVarArgs(soa, obj, mid, args).GetD();
1478  }
1479
1480  static jdouble CallNonvirtualDoubleMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1481                                             jvalue* args) {
1482    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodA, obj);
1483    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodA, mid);
1484    ScopedObjectAccess soa(env);
1485    return InvokeWithJValues(soa, obj, mid, args).GetD();
1486  }
1487
1488  static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
1489    va_list ap;
1490    va_start(ap, mid);
1491    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethod, obj);
1492    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethod, mid);
1493    ScopedObjectAccess soa(env);
1494    InvokeWithVarArgs(soa, obj, mid, ap);
1495    va_end(ap);
1496  }
1497
1498  static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1499                                        va_list args) {
1500    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodV, obj);
1501    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodV, mid);
1502    ScopedObjectAccess soa(env);
1503    InvokeWithVarArgs(soa, obj, mid, args);
1504  }
1505
1506  static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
1507                                        jvalue* args) {
1508    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodA, obj);
1509    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodA, mid);
1510    ScopedObjectAccess soa(env);
1511    InvokeWithJValues(soa, obj, mid, args);
1512  }
1513
1514  static jfieldID GetFieldID(JNIEnv* env, jclass java_class, const char* name, const char* sig) {
1515    CHECK_NON_NULL_ARGUMENT(GetFieldID, java_class);
1516    CHECK_NON_NULL_ARGUMENT(GetFieldID, name);
1517    CHECK_NON_NULL_ARGUMENT(GetFieldID, sig);
1518    ScopedObjectAccess soa(env);
1519    return FindFieldID(soa, java_class, name, sig, false);
1520  }
1521
1522  static jfieldID GetStaticFieldID(JNIEnv* env, jclass java_class, const char* name,
1523                                   const char* sig) {
1524    CHECK_NON_NULL_ARGUMENT(GetStaticFieldID, java_class);
1525    CHECK_NON_NULL_ARGUMENT(GetStaticFieldID, name);
1526    CHECK_NON_NULL_ARGUMENT(GetFieldID, sig);
1527    ScopedObjectAccess soa(env);
1528    return FindFieldID(soa, java_class, name, sig, true);
1529  }
1530
1531  static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fid) {
1532    CHECK_NON_NULL_ARGUMENT(GetObjectField, obj);
1533    CHECK_NON_NULL_ARGUMENT(GetObjectField, fid);
1534    ScopedObjectAccess soa(env);
1535    Object* o = soa.Decode<Object*>(obj);
1536    ArtField* f = soa.DecodeField(fid);
1537    return soa.AddLocalReference<jobject>(f->GetObject(o));
1538  }
1539
1540  static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) {
1541    CHECK_NON_NULL_ARGUMENT(GetStaticObjectField, fid);
1542    ScopedObjectAccess soa(env);
1543    ArtField* f = soa.DecodeField(fid);
1544    return soa.AddLocalReference<jobject>(f->GetObject(f->GetDeclaringClass()));
1545  }
1546
1547  static void SetObjectField(JNIEnv* env, jobject java_object, jfieldID fid, jobject java_value) {
1548    CHECK_NON_NULL_ARGUMENT(SetObjectField, java_object);
1549    CHECK_NON_NULL_ARGUMENT(SetObjectField, fid);
1550    ScopedObjectAccess soa(env);
1551    Object* o = soa.Decode<Object*>(java_object);
1552    Object* v = soa.Decode<Object*>(java_value);
1553    ArtField* f = soa.DecodeField(fid);
1554    f->SetObject(o, v);
1555  }
1556
1557  static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
1558    CHECK_NON_NULL_ARGUMENT(SetStaticObjectField, fid);
1559    ScopedObjectAccess soa(env);
1560    Object* v = soa.Decode<Object*>(java_value);
1561    ArtField* f = soa.DecodeField(fid);
1562    f->SetObject(f->GetDeclaringClass(), v);
1563  }
1564
1565#define GET_PRIMITIVE_FIELD(fn, instance) \
1566  CHECK_NON_NULL_ARGUMENT(Get #fn Field, instance); \
1567  CHECK_NON_NULL_ARGUMENT(Get #fn Field, fid); \
1568  ScopedObjectAccess soa(env); \
1569  Object* o = soa.Decode<Object*>(instance); \
1570  ArtField* f = soa.DecodeField(fid); \
1571  return f->Get ##fn (o)
1572
1573#define GET_STATIC_PRIMITIVE_FIELD(fn) \
1574  CHECK_NON_NULL_ARGUMENT(GetStatic #fn Field, fid); \
1575  ScopedObjectAccess soa(env); \
1576  ArtField* f = soa.DecodeField(fid); \
1577  return f->Get ##fn (f->GetDeclaringClass())
1578
1579#define SET_PRIMITIVE_FIELD(fn, instance, value) \
1580  CHECK_NON_NULL_ARGUMENT(Set #fn Field, instance); \
1581  CHECK_NON_NULL_ARGUMENT(Set #fn Field, fid); \
1582  ScopedObjectAccess soa(env); \
1583  Object* o = soa.Decode<Object*>(instance); \
1584  ArtField* f = soa.DecodeField(fid); \
1585  f->Set ##fn(o, value)
1586
1587#define SET_STATIC_PRIMITIVE_FIELD(fn, value) \
1588  CHECK_NON_NULL_ARGUMENT(SetStatic #fn Field, fid); \
1589  ScopedObjectAccess soa(env); \
1590  ArtField* f = soa.DecodeField(fid); \
1591  f->Set ##fn(f->GetDeclaringClass(), value)
1592
1593  static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fid) {
1594    GET_PRIMITIVE_FIELD(Boolean, obj);
1595  }
1596
1597  static jbyte GetByteField(JNIEnv* env, jobject obj, jfieldID fid) {
1598    GET_PRIMITIVE_FIELD(Byte, obj);
1599  }
1600
1601  static jchar GetCharField(JNIEnv* env, jobject obj, jfieldID fid) {
1602    GET_PRIMITIVE_FIELD(Char, obj);
1603  }
1604
1605  static jshort GetShortField(JNIEnv* env, jobject obj, jfieldID fid) {
1606    GET_PRIMITIVE_FIELD(Short, obj);
1607  }
1608
1609  static jint GetIntField(JNIEnv* env, jobject obj, jfieldID fid) {
1610    GET_PRIMITIVE_FIELD(Int, obj);
1611  }
1612
1613  static jlong GetLongField(JNIEnv* env, jobject obj, jfieldID fid) {
1614    GET_PRIMITIVE_FIELD(Long, obj);
1615  }
1616
1617  static jfloat GetFloatField(JNIEnv* env, jobject obj, jfieldID fid) {
1618    GET_PRIMITIVE_FIELD(Float, obj);
1619  }
1620
1621  static jdouble GetDoubleField(JNIEnv* env, jobject obj, jfieldID fid) {
1622    GET_PRIMITIVE_FIELD(Double, obj);
1623  }
1624
1625  static jboolean GetStaticBooleanField(JNIEnv* env, jclass, jfieldID fid) {
1626    GET_STATIC_PRIMITIVE_FIELD(Boolean);
1627  }
1628
1629  static jbyte GetStaticByteField(JNIEnv* env, jclass, jfieldID fid) {
1630    GET_STATIC_PRIMITIVE_FIELD(Byte);
1631  }
1632
1633  static jchar GetStaticCharField(JNIEnv* env, jclass, jfieldID fid) {
1634    GET_STATIC_PRIMITIVE_FIELD(Char);
1635  }
1636
1637  static jshort GetStaticShortField(JNIEnv* env, jclass, jfieldID fid) {
1638    GET_STATIC_PRIMITIVE_FIELD(Short);
1639  }
1640
1641  static jint GetStaticIntField(JNIEnv* env, jclass, jfieldID fid) {
1642    GET_STATIC_PRIMITIVE_FIELD(Int);
1643  }
1644
1645  static jlong GetStaticLongField(JNIEnv* env, jclass, jfieldID fid) {
1646    GET_STATIC_PRIMITIVE_FIELD(Long);
1647  }
1648
1649  static jfloat GetStaticFloatField(JNIEnv* env, jclass, jfieldID fid) {
1650    GET_STATIC_PRIMITIVE_FIELD(Float);
1651  }
1652
1653  static jdouble GetStaticDoubleField(JNIEnv* env, jclass, jfieldID fid) {
1654    GET_STATIC_PRIMITIVE_FIELD(Double);
1655  }
1656
1657  static void SetBooleanField(JNIEnv* env, jobject obj, jfieldID fid, jboolean v) {
1658    SET_PRIMITIVE_FIELD(Boolean, obj, v);
1659  }
1660
1661  static void SetByteField(JNIEnv* env, jobject obj, jfieldID fid, jbyte v) {
1662    SET_PRIMITIVE_FIELD(Byte, obj, v);
1663  }
1664
1665  static void SetCharField(JNIEnv* env, jobject obj, jfieldID fid, jchar v) {
1666    SET_PRIMITIVE_FIELD(Char, obj, v);
1667  }
1668
1669  static void SetFloatField(JNIEnv* env, jobject obj, jfieldID fid, jfloat v) {
1670    SET_PRIMITIVE_FIELD(Float, obj, v);
1671  }
1672
1673  static void SetDoubleField(JNIEnv* env, jobject obj, jfieldID fid, jdouble v) {
1674    SET_PRIMITIVE_FIELD(Double, obj, v);
1675  }
1676
1677  static void SetIntField(JNIEnv* env, jobject obj, jfieldID fid, jint v) {
1678    SET_PRIMITIVE_FIELD(Int, obj, v);
1679  }
1680
1681  static void SetLongField(JNIEnv* env, jobject obj, jfieldID fid, jlong v) {
1682    SET_PRIMITIVE_FIELD(Long, obj, v);
1683  }
1684
1685  static void SetShortField(JNIEnv* env, jobject obj, jfieldID fid, jshort v) {
1686    SET_PRIMITIVE_FIELD(Short, obj, v);
1687  }
1688
1689  static void SetStaticBooleanField(JNIEnv* env, jclass, jfieldID fid, jboolean v) {
1690    SET_STATIC_PRIMITIVE_FIELD(Boolean, v);
1691  }
1692
1693  static void SetStaticByteField(JNIEnv* env, jclass, jfieldID fid, jbyte v) {
1694    SET_STATIC_PRIMITIVE_FIELD(Byte, v);
1695  }
1696
1697  static void SetStaticCharField(JNIEnv* env, jclass, jfieldID fid, jchar v) {
1698    SET_STATIC_PRIMITIVE_FIELD(Char, v);
1699  }
1700
1701  static void SetStaticFloatField(JNIEnv* env, jclass, jfieldID fid, jfloat v) {
1702    SET_STATIC_PRIMITIVE_FIELD(Float, v);
1703  }
1704
1705  static void SetStaticDoubleField(JNIEnv* env, jclass, jfieldID fid, jdouble v) {
1706    SET_STATIC_PRIMITIVE_FIELD(Double, v);
1707  }
1708
1709  static void SetStaticIntField(JNIEnv* env, jclass, jfieldID fid, jint v) {
1710    SET_STATIC_PRIMITIVE_FIELD(Int, v);
1711  }
1712
1713  static void SetStaticLongField(JNIEnv* env, jclass, jfieldID fid, jlong v) {
1714    SET_STATIC_PRIMITIVE_FIELD(Long, v);
1715  }
1716
1717  static void SetStaticShortField(JNIEnv* env, jclass, jfieldID fid, jshort v) {
1718    SET_STATIC_PRIMITIVE_FIELD(Short, v);
1719  }
1720
1721  static jobject CallStaticObjectMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
1722    va_list ap;
1723    va_start(ap, mid);
1724    CHECK_NON_NULL_ARGUMENT(CallStaticObjectMethod, mid);
1725    ScopedObjectAccess soa(env);
1726    JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
1727    jobject local_result = soa.AddLocalReference<jobject>(result.GetL());
1728    va_end(ap);
1729    return local_result;
1730  }
1731
1732  static jobject CallStaticObjectMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
1733    CHECK_NON_NULL_ARGUMENT(CallStaticObjectMethodV, mid);
1734    ScopedObjectAccess soa(env);
1735    JValue result(InvokeWithVarArgs(soa, NULL, mid, args));
1736    return soa.AddLocalReference<jobject>(result.GetL());
1737  }
1738
1739  static jobject CallStaticObjectMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
1740    CHECK_NON_NULL_ARGUMENT(CallStaticObjectMethodA, mid);
1741    ScopedObjectAccess soa(env);
1742    JValue result(InvokeWithJValues(soa, NULL, mid, args));
1743    return soa.AddLocalReference<jobject>(result.GetL());
1744  }
1745
1746  static jboolean CallStaticBooleanMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
1747    va_list ap;
1748    va_start(ap, mid);
1749    CHECK_NON_NULL_ARGUMENT(CallStaticBooleanMethod, mid);
1750    ScopedObjectAccess soa(env);
1751    JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
1752    va_end(ap);
1753    return result.GetZ();
1754  }
1755
1756  static jboolean CallStaticBooleanMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
1757    CHECK_NON_NULL_ARGUMENT(CallStaticBooleanMethodV, mid);
1758    ScopedObjectAccess soa(env);
1759    return InvokeWithVarArgs(soa, NULL, mid, args).GetZ();
1760  }
1761
1762  static jboolean CallStaticBooleanMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
1763    CHECK_NON_NULL_ARGUMENT(CallStaticBooleanMethodA, mid);
1764    ScopedObjectAccess soa(env);
1765    return InvokeWithJValues(soa, NULL, mid, args).GetZ();
1766  }
1767
1768  static jbyte CallStaticByteMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
1769    va_list ap;
1770    va_start(ap, mid);
1771    CHECK_NON_NULL_ARGUMENT(CallStaticByteMethod, mid);
1772    ScopedObjectAccess soa(env);
1773    JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
1774    va_end(ap);
1775    return result.GetB();
1776  }
1777
1778  static jbyte CallStaticByteMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
1779    CHECK_NON_NULL_ARGUMENT(CallStaticByteMethodV, mid);
1780    ScopedObjectAccess soa(env);
1781    return InvokeWithVarArgs(soa, NULL, mid, args).GetB();
1782  }
1783
1784  static jbyte CallStaticByteMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
1785    CHECK_NON_NULL_ARGUMENT(CallStaticByteMethodA, mid);
1786    ScopedObjectAccess soa(env);
1787    return InvokeWithJValues(soa, NULL, mid, args).GetB();
1788  }
1789
1790  static jchar CallStaticCharMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
1791    va_list ap;
1792    va_start(ap, mid);
1793    CHECK_NON_NULL_ARGUMENT(CallStaticCharMethod, mid);
1794    ScopedObjectAccess soa(env);
1795    JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
1796    va_end(ap);
1797    return result.GetC();
1798  }
1799
1800  static jchar CallStaticCharMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
1801    CHECK_NON_NULL_ARGUMENT(CallStaticCharMethodV, mid);
1802    ScopedObjectAccess soa(env);
1803    return InvokeWithVarArgs(soa, NULL, mid, args).GetC();
1804  }
1805
1806  static jchar CallStaticCharMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
1807    CHECK_NON_NULL_ARGUMENT(CallStaticCharMethodA, mid);
1808    ScopedObjectAccess soa(env);
1809    return InvokeWithJValues(soa, NULL, mid, args).GetC();
1810  }
1811
1812  static jshort CallStaticShortMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
1813    va_list ap;
1814    va_start(ap, mid);
1815    CHECK_NON_NULL_ARGUMENT(CallStaticShortMethod, mid);
1816    ScopedObjectAccess soa(env);
1817    JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
1818    va_end(ap);
1819    return result.GetS();
1820  }
1821
1822  static jshort CallStaticShortMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
1823    CHECK_NON_NULL_ARGUMENT(CallStaticShortMethodV, mid);
1824    ScopedObjectAccess soa(env);
1825    return InvokeWithVarArgs(soa, NULL, mid, args).GetS();
1826  }
1827
1828  static jshort CallStaticShortMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
1829    CHECK_NON_NULL_ARGUMENT(CallStaticShortMethodA, mid);
1830    ScopedObjectAccess soa(env);
1831    return InvokeWithJValues(soa, NULL, mid, args).GetS();
1832  }
1833
1834  static jint CallStaticIntMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
1835    va_list ap;
1836    va_start(ap, mid);
1837    CHECK_NON_NULL_ARGUMENT(CallStaticIntMethod, mid);
1838    ScopedObjectAccess soa(env);
1839    JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
1840    va_end(ap);
1841    return result.GetI();
1842  }
1843
1844  static jint CallStaticIntMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
1845    CHECK_NON_NULL_ARGUMENT(CallStaticIntMethodV, mid);
1846    ScopedObjectAccess soa(env);
1847    return InvokeWithVarArgs(soa, NULL, mid, args).GetI();
1848  }
1849
1850  static jint CallStaticIntMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
1851    CHECK_NON_NULL_ARGUMENT(CallStaticIntMethodA, mid);
1852    ScopedObjectAccess soa(env);
1853    return InvokeWithJValues(soa, NULL, mid, args).GetI();
1854  }
1855
1856  static jlong CallStaticLongMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
1857    va_list ap;
1858    va_start(ap, mid);
1859    CHECK_NON_NULL_ARGUMENT(CallStaticLongMethod, mid);
1860    ScopedObjectAccess soa(env);
1861    JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
1862    va_end(ap);
1863    return result.GetJ();
1864  }
1865
1866  static jlong CallStaticLongMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
1867    CHECK_NON_NULL_ARGUMENT(CallStaticLongMethodV, mid);
1868    ScopedObjectAccess soa(env);
1869    return InvokeWithVarArgs(soa, NULL, mid, args).GetJ();
1870  }
1871
1872  static jlong CallStaticLongMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
1873    CHECK_NON_NULL_ARGUMENT(CallStaticLongMethodA, mid);
1874    ScopedObjectAccess soa(env);
1875    return InvokeWithJValues(soa, NULL, mid, args).GetJ();
1876  }
1877
1878  static jfloat CallStaticFloatMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
1879    va_list ap;
1880    va_start(ap, mid);
1881    CHECK_NON_NULL_ARGUMENT(CallStaticFloatMethod, mid);
1882    ScopedObjectAccess soa(env);
1883    JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
1884    va_end(ap);
1885    return result.GetF();
1886  }
1887
1888  static jfloat CallStaticFloatMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
1889    CHECK_NON_NULL_ARGUMENT(CallStaticFloatMethodV, mid);
1890    ScopedObjectAccess soa(env);
1891    return InvokeWithVarArgs(soa, NULL, mid, args).GetF();
1892  }
1893
1894  static jfloat CallStaticFloatMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
1895    CHECK_NON_NULL_ARGUMENT(CallStaticFloatMethodA, mid);
1896    ScopedObjectAccess soa(env);
1897    return InvokeWithJValues(soa, NULL, mid, args).GetF();
1898  }
1899
1900  static jdouble CallStaticDoubleMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
1901    va_list ap;
1902    va_start(ap, mid);
1903    CHECK_NON_NULL_ARGUMENT(CallStaticDoubleMethod, mid);
1904    ScopedObjectAccess soa(env);
1905    JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
1906    va_end(ap);
1907    return result.GetD();
1908  }
1909
1910  static jdouble CallStaticDoubleMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
1911    CHECK_NON_NULL_ARGUMENT(CallStaticDoubleMethodV, mid);
1912    ScopedObjectAccess soa(env);
1913    return InvokeWithVarArgs(soa, NULL, mid, args).GetD();
1914  }
1915
1916  static jdouble CallStaticDoubleMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
1917    CHECK_NON_NULL_ARGUMENT(CallStaticDoubleMethodA, mid);
1918    ScopedObjectAccess soa(env);
1919    return InvokeWithJValues(soa, NULL, mid, args).GetD();
1920  }
1921
1922  static void CallStaticVoidMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
1923    va_list ap;
1924    va_start(ap, mid);
1925    CHECK_NON_NULL_ARGUMENT(CallStaticVoidMethod, mid);
1926    ScopedObjectAccess soa(env);
1927    InvokeWithVarArgs(soa, NULL, mid, ap);
1928    va_end(ap);
1929  }
1930
1931  static void CallStaticVoidMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
1932    CHECK_NON_NULL_ARGUMENT(CallStaticVoidMethodV, mid);
1933    ScopedObjectAccess soa(env);
1934    InvokeWithVarArgs(soa, NULL, mid, args);
1935  }
1936
1937  static void CallStaticVoidMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
1938    CHECK_NON_NULL_ARGUMENT(CallStaticVoidMethodA, mid);
1939    ScopedObjectAccess soa(env);
1940    InvokeWithJValues(soa, NULL, mid, args);
1941  }
1942
1943  static jstring NewString(JNIEnv* env, const jchar* chars, jsize char_count) {
1944    if (UNLIKELY(chars == NULL && char_count > 0)) { \
1945      JniAbortF("NewString", "char == null && char_count > 0"); \
1946    }
1947    ScopedObjectAccess soa(env);
1948    String* result = String::AllocFromUtf16(soa.Self(), char_count, chars);
1949    return soa.AddLocalReference<jstring>(result);
1950  }
1951
1952  static jstring NewStringUTF(JNIEnv* env, const char* utf) {
1953    if (utf == NULL) {
1954      return NULL;
1955    }
1956    ScopedObjectAccess soa(env);
1957    String* result = String::AllocFromModifiedUtf8(soa.Self(), utf);
1958    return soa.AddLocalReference<jstring>(result);
1959  }
1960
1961  static jsize GetStringLength(JNIEnv* env, jstring java_string) {
1962    CHECK_NON_NULL_ARGUMENT(GetStringLength, java_string);
1963    ScopedObjectAccess soa(env);
1964    return soa.Decode<String*>(java_string)->GetLength();
1965  }
1966
1967  static jsize GetStringUTFLength(JNIEnv* env, jstring java_string) {
1968    CHECK_NON_NULL_ARGUMENT(GetStringLength, java_string);
1969    ScopedObjectAccess soa(env);
1970    return soa.Decode<String*>(java_string)->GetUtfLength();
1971  }
1972
1973  static void GetStringRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
1974                              jchar* buf) {
1975    CHECK_NON_NULL_ARGUMENT(GetStringRegion, java_string);
1976    ScopedObjectAccess soa(env);
1977    String* s = soa.Decode<String*>(java_string);
1978    if (start < 0 || length < 0 || start + length > s->GetLength()) {
1979      ThrowSIOOBE(soa, start, length, s->GetLength());
1980    } else {
1981      CHECK_NON_NULL_MEMCPY_ARGUMENT(GetStringRegion, length, buf);
1982      const jchar* chars = s->GetCharArray()->GetData() + s->GetOffset();
1983      memcpy(buf, chars + start, length * sizeof(jchar));
1984    }
1985  }
1986
1987  static void GetStringUTFRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
1988                                 char* buf) {
1989    CHECK_NON_NULL_ARGUMENT(GetStringUTFRegion, java_string);
1990    ScopedObjectAccess soa(env);
1991    String* s = soa.Decode<String*>(java_string);
1992    if (start < 0 || length < 0 || start + length > s->GetLength()) {
1993      ThrowSIOOBE(soa, start, length, s->GetLength());
1994    } else {
1995      CHECK_NON_NULL_MEMCPY_ARGUMENT(GetStringUTFRegion, length, buf);
1996      const jchar* chars = s->GetCharArray()->GetData() + s->GetOffset();
1997      ConvertUtf16ToModifiedUtf8(buf, chars + start, length);
1998    }
1999  }
2000
2001  static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* is_copy) {
2002    CHECK_NON_NULL_ARGUMENT(GetStringUTFRegion, java_string);
2003    ScopedObjectAccess soa(env);
2004    String* s = soa.Decode<String*>(java_string);
2005    const CharArray* chars = s->GetCharArray();
2006    PinPrimitiveArray(soa, chars);
2007    if (is_copy != NULL) {
2008      *is_copy = JNI_FALSE;
2009    }
2010    return chars->GetData() + s->GetOffset();
2011  }
2012
2013  static void ReleaseStringChars(JNIEnv* env, jstring java_string, const jchar*) {
2014    CHECK_NON_NULL_ARGUMENT(GetStringUTFRegion, java_string);
2015    ScopedObjectAccess soa(env);
2016    UnpinPrimitiveArray(soa, soa.Decode<String*>(java_string)->GetCharArray());
2017  }
2018
2019  static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* is_copy) {
2020    return GetStringChars(env, java_string, is_copy);
2021  }
2022
2023  static void ReleaseStringCritical(JNIEnv* env, jstring java_string, const jchar* chars) {
2024    return ReleaseStringChars(env, java_string, chars);
2025  }
2026
2027  static const char* GetStringUTFChars(JNIEnv* env, jstring java_string, jboolean* is_copy) {
2028    if (java_string == NULL) {
2029      return NULL;
2030    }
2031    if (is_copy != NULL) {
2032      *is_copy = JNI_TRUE;
2033    }
2034    ScopedObjectAccess soa(env);
2035    String* s = soa.Decode<String*>(java_string);
2036    size_t byte_count = s->GetUtfLength();
2037    char* bytes = new char[byte_count + 1];
2038    CHECK(bytes != NULL);  // bionic aborts anyway.
2039    const uint16_t* chars = s->GetCharArray()->GetData() + s->GetOffset();
2040    ConvertUtf16ToModifiedUtf8(bytes, chars, s->GetLength());
2041    bytes[byte_count] = '\0';
2042    return bytes;
2043  }
2044
2045  static void ReleaseStringUTFChars(JNIEnv* env, jstring, const char* chars) {
2046    delete[] chars;
2047  }
2048
2049  static jsize GetArrayLength(JNIEnv* env, jarray java_array) {
2050    CHECK_NON_NULL_ARGUMENT(GetArrayLength, java_array);
2051    ScopedObjectAccess soa(env);
2052    Object* obj = soa.Decode<Object*>(java_array);
2053    if (UNLIKELY(!obj->IsArrayInstance())) {
2054      JniAbortF("GetArrayLength", "not an array: %s", PrettyTypeOf(obj).c_str());
2055    }
2056    Array* array = obj->AsArray();
2057    return array->GetLength();
2058  }
2059
2060  static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index) {
2061    CHECK_NON_NULL_ARGUMENT(GetObjectArrayElement, java_array);
2062    ScopedObjectAccess soa(env);
2063    ObjectArray<Object>* array = soa.Decode<ObjectArray<Object>*>(java_array);
2064    return soa.AddLocalReference<jobject>(array->Get(index));
2065  }
2066
2067  static void SetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index,
2068                                    jobject java_value) {
2069    CHECK_NON_NULL_ARGUMENT(SetObjectArrayElement, java_array);
2070    ScopedObjectAccess soa(env);
2071    ObjectArray<Object>* array = soa.Decode<ObjectArray<Object>*>(java_array);
2072    Object* value = soa.Decode<Object*>(java_value);
2073    array->Set(index, value);
2074  }
2075
2076  static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2077    ScopedObjectAccess soa(env);
2078    return NewPrimitiveArray<jbooleanArray, BooleanArray>(soa, length);
2079  }
2080
2081  static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2082    ScopedObjectAccess soa(env);
2083    return NewPrimitiveArray<jbyteArray, ByteArray>(soa, length);
2084  }
2085
2086  static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2087    ScopedObjectAccess soa(env);
2088    return NewPrimitiveArray<jcharArray, CharArray>(soa, length);
2089  }
2090
2091  static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2092    ScopedObjectAccess soa(env);
2093    return NewPrimitiveArray<jdoubleArray, DoubleArray>(soa, length);
2094  }
2095
2096  static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2097    ScopedObjectAccess soa(env);
2098    return NewPrimitiveArray<jfloatArray, FloatArray>(soa, length);
2099  }
2100
2101  static jintArray NewIntArray(JNIEnv* env, jsize length) {
2102    ScopedObjectAccess soa(env);
2103    return NewPrimitiveArray<jintArray, IntArray>(soa, length);
2104  }
2105
2106  static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2107    ScopedObjectAccess soa(env);
2108    return NewPrimitiveArray<jlongArray, LongArray>(soa, length);
2109  }
2110
2111  static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_jclass, jobject initial_element) {
2112    if (length < 0) {
2113      JniAbortF("NewObjectArray", "negative array length: %d", length);
2114    }
2115
2116    // Compute the array class corresponding to the given element class.
2117    ScopedObjectAccess soa(env);
2118    Class* element_class = soa.Decode<Class*>(element_jclass);
2119    std::string descriptor;
2120    descriptor += "[";
2121    descriptor += ClassHelper(element_class).GetDescriptor();
2122
2123    // Find the class.
2124    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
2125    Class* array_class = class_linker->FindClass(descriptor.c_str(),
2126                                                 element_class->GetClassLoader());
2127    if (array_class == NULL) {
2128      return NULL;
2129    }
2130
2131    // Allocate and initialize if necessary.
2132    ObjectArray<Object>* result = ObjectArray<Object>::Alloc(soa.Self(), array_class, length);
2133    if (initial_element != NULL) {
2134      Object* initial_object = soa.Decode<Object*>(initial_element);
2135      for (jsize i = 0; i < length; ++i) {
2136        result->Set(i, initial_object);
2137      }
2138    }
2139    return soa.AddLocalReference<jobjectArray>(result);
2140  }
2141
2142  static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2143    ScopedObjectAccess soa(env);
2144    return NewPrimitiveArray<jshortArray, ShortArray>(soa, length);
2145  }
2146
2147  static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray java_array, jboolean* is_copy) {
2148    CHECK_NON_NULL_ARGUMENT(GetPrimitiveArrayCritical, java_array);
2149    ScopedObjectAccess soa(env);
2150    Array* array = soa.Decode<Array*>(java_array);
2151    PinPrimitiveArray(soa, array);
2152    if (is_copy != NULL) {
2153      *is_copy = JNI_FALSE;
2154    }
2155    return array->GetRawData(array->GetClass()->GetComponentSize());
2156  }
2157
2158  static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void*, jint mode) {
2159    CHECK_NON_NULL_ARGUMENT(ReleasePrimitiveArrayCritical, array);
2160    ReleasePrimitiveArray(env, array, mode);
2161  }
2162
2163  static jboolean* GetBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* is_copy) {
2164    CHECK_NON_NULL_ARGUMENT(GetBooleanArrayElements, array);
2165    ScopedObjectAccess soa(env);
2166    return GetPrimitiveArray<jbooleanArray, jboolean*, BooleanArray>(soa, array, is_copy);
2167  }
2168
2169  static jbyte* GetByteArrayElements(JNIEnv* env, jbyteArray array, jboolean* is_copy) {
2170    CHECK_NON_NULL_ARGUMENT(GetByteArrayElements, array);
2171    ScopedObjectAccess soa(env);
2172    return GetPrimitiveArray<jbyteArray, jbyte*, ByteArray>(soa, array, is_copy);
2173  }
2174
2175  static jchar* GetCharArrayElements(JNIEnv* env, jcharArray array, jboolean* is_copy) {
2176    CHECK_NON_NULL_ARGUMENT(GetCharArrayElements, array);
2177    ScopedObjectAccess soa(env);
2178    return GetPrimitiveArray<jcharArray, jchar*, CharArray>(soa, array, is_copy);
2179  }
2180
2181  static jdouble* GetDoubleArrayElements(JNIEnv* env, jdoubleArray array, jboolean* is_copy) {
2182    CHECK_NON_NULL_ARGUMENT(GetDoubleArrayElements, array);
2183    ScopedObjectAccess soa(env);
2184    return GetPrimitiveArray<jdoubleArray, jdouble*, DoubleArray>(soa, array, is_copy);
2185  }
2186
2187  static jfloat* GetFloatArrayElements(JNIEnv* env, jfloatArray array, jboolean* is_copy) {
2188    CHECK_NON_NULL_ARGUMENT(GetFloatArrayElements, array);
2189    ScopedObjectAccess soa(env);
2190    return GetPrimitiveArray<jfloatArray, jfloat*, FloatArray>(soa, array, is_copy);
2191  }
2192
2193  static jint* GetIntArrayElements(JNIEnv* env, jintArray array, jboolean* is_copy) {
2194    CHECK_NON_NULL_ARGUMENT(GetIntArrayElements, array);
2195    ScopedObjectAccess soa(env);
2196    return GetPrimitiveArray<jintArray, jint*, IntArray>(soa, array, is_copy);
2197  }
2198
2199  static jlong* GetLongArrayElements(JNIEnv* env, jlongArray array, jboolean* is_copy) {
2200    CHECK_NON_NULL_ARGUMENT(GetLongArrayElements, array);
2201    ScopedObjectAccess soa(env);
2202    return GetPrimitiveArray<jlongArray, jlong*, LongArray>(soa, array, is_copy);
2203  }
2204
2205  static jshort* GetShortArrayElements(JNIEnv* env, jshortArray array, jboolean* is_copy) {
2206    CHECK_NON_NULL_ARGUMENT(GetShortArrayElements, array);
2207    ScopedObjectAccess soa(env);
2208    return GetPrimitiveArray<jshortArray, jshort*, ShortArray>(soa, array, is_copy);
2209  }
2210
2211  static void ReleaseBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean*, jint mode) {
2212    ReleasePrimitiveArray(env, array, mode);
2213  }
2214
2215  static void ReleaseByteArrayElements(JNIEnv* env, jbyteArray array, jbyte*, jint mode) {
2216    ReleasePrimitiveArray(env, array, mode);
2217  }
2218
2219  static void ReleaseCharArrayElements(JNIEnv* env, jcharArray array, jchar*, jint mode) {
2220    ReleasePrimitiveArray(env, array, mode);
2221  }
2222
2223  static void ReleaseDoubleArrayElements(JNIEnv* env, jdoubleArray array, jdouble*, jint mode) {
2224    ReleasePrimitiveArray(env, array, mode);
2225  }
2226
2227  static void ReleaseFloatArrayElements(JNIEnv* env, jfloatArray array, jfloat*, jint mode) {
2228    ReleasePrimitiveArray(env, array, mode);
2229  }
2230
2231  static void ReleaseIntArrayElements(JNIEnv* env, jintArray array, jint*, jint mode) {
2232    ReleasePrimitiveArray(env, array, mode);
2233  }
2234
2235  static void ReleaseLongArrayElements(JNIEnv* env, jlongArray array, jlong*, jint mode) {
2236    ReleasePrimitiveArray(env, array, mode);
2237  }
2238
2239  static void ReleaseShortArrayElements(JNIEnv* env, jshortArray array, jshort*, jint mode) {
2240    ReleasePrimitiveArray(env, array, mode);
2241  }
2242
2243  static void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length,
2244                                    jboolean* buf) {
2245    ScopedObjectAccess soa(env);
2246    GetPrimitiveArrayRegion<jbooleanArray, jboolean, BooleanArray>(soa, array, start, length, buf);
2247  }
2248
2249  static void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length,
2250                                 jbyte* buf) {
2251    ScopedObjectAccess soa(env);
2252    GetPrimitiveArrayRegion<jbyteArray, jbyte, ByteArray>(soa, array, start, length, buf);
2253  }
2254
2255  static void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length,
2256                                 jchar* buf) {
2257    ScopedObjectAccess soa(env);
2258    GetPrimitiveArrayRegion<jcharArray, jchar, CharArray>(soa, array, start, length, buf);
2259  }
2260
2261  static void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length,
2262                                   jdouble* buf) {
2263    ScopedObjectAccess soa(env);
2264    GetPrimitiveArrayRegion<jdoubleArray, jdouble, DoubleArray>(soa, array, start, length, buf);
2265  }
2266
2267  static void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length,
2268                                  jfloat* buf) {
2269    ScopedObjectAccess soa(env);
2270    GetPrimitiveArrayRegion<jfloatArray, jfloat, FloatArray>(soa, array, start, length, buf);
2271  }
2272
2273  static void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length,
2274                                jint* buf) {
2275    ScopedObjectAccess soa(env);
2276    GetPrimitiveArrayRegion<jintArray, jint, IntArray>(soa, array, start, length, buf);
2277  }
2278
2279  static void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length,
2280                                 jlong* buf) {
2281    ScopedObjectAccess soa(env);
2282    GetPrimitiveArrayRegion<jlongArray, jlong, LongArray>(soa, array, start, length, buf);
2283  }
2284
2285  static void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length,
2286                                  jshort* buf) {
2287    ScopedObjectAccess soa(env);
2288    GetPrimitiveArrayRegion<jshortArray, jshort, ShortArray>(soa, array, start, length, buf);
2289  }
2290
2291  static void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length,
2292                                    const jboolean* buf) {
2293    ScopedObjectAccess soa(env);
2294    SetPrimitiveArrayRegion<jbooleanArray, jboolean, BooleanArray>(soa, array, start, length, buf);
2295  }
2296
2297  static void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length,
2298                                 const jbyte* buf) {
2299    ScopedObjectAccess soa(env);
2300    SetPrimitiveArrayRegion<jbyteArray, jbyte, ByteArray>(soa, array, start, length, buf);
2301  }
2302
2303  static void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length,
2304                                 const jchar* buf) {
2305    ScopedObjectAccess soa(env);
2306    SetPrimitiveArrayRegion<jcharArray, jchar, CharArray>(soa, array, start, length, buf);
2307  }
2308
2309  static void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length,
2310                                   const jdouble* buf) {
2311    ScopedObjectAccess soa(env);
2312    SetPrimitiveArrayRegion<jdoubleArray, jdouble, DoubleArray>(soa, array, start, length, buf);
2313  }
2314
2315  static void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length,
2316                                  const jfloat* buf) {
2317    ScopedObjectAccess soa(env);
2318    SetPrimitiveArrayRegion<jfloatArray, jfloat, FloatArray>(soa, array, start, length, buf);
2319  }
2320
2321  static void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length,
2322                                const jint* buf) {
2323    ScopedObjectAccess soa(env);
2324    SetPrimitiveArrayRegion<jintArray, jint, IntArray>(soa, array, start, length, buf);
2325  }
2326
2327  static void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length,
2328                                 const jlong* buf) {
2329    ScopedObjectAccess soa(env);
2330    SetPrimitiveArrayRegion<jlongArray, jlong, LongArray>(soa, array, start, length, buf);
2331  }
2332
2333  static void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length,
2334                                  const jshort* buf) {
2335    ScopedObjectAccess soa(env);
2336    SetPrimitiveArrayRegion<jshortArray, jshort, ShortArray>(soa, array, start, length, buf);
2337  }
2338
2339  static jint RegisterNatives(JNIEnv* env, jclass java_class, const JNINativeMethod* methods,
2340                              jint method_count) {
2341    return RegisterNativeMethods(env, java_class, methods, method_count, true);
2342  }
2343
2344  static jint RegisterNativeMethods(JNIEnv* env, jclass java_class, const JNINativeMethod* methods,
2345                                    jint method_count, bool return_errors) {
2346    if (UNLIKELY(method_count < 0)) {
2347      JniAbortF("RegisterNatives", "negative method count: %d", method_count);
2348      return JNI_ERR;  // Not reached.
2349    }
2350    CHECK_NON_NULL_ARGUMENT(RegisterNatives, java_class);
2351    ScopedObjectAccess soa(env);
2352    Class* c = soa.Decode<Class*>(java_class);
2353    if (UNLIKELY(method_count == 0)) {
2354      LOG(WARNING) << "JNI RegisterNativeMethods: attempt to register 0 native methods for "
2355          << PrettyDescriptor(c);
2356      return JNI_OK;
2357    }
2358    CHECK_NON_NULL_ARGUMENT(RegisterNatives, methods);
2359    for (jint i = 0; i < method_count; ++i) {
2360      const char* name = methods[i].name;
2361      const char* sig = methods[i].signature;
2362
2363      if (*sig == '!') {
2364        // TODO: fast jni. it's too noisy to log all these.
2365        ++sig;
2366      }
2367
2368      ArtMethod* m = c->FindDirectMethod(name, sig);
2369      if (m == NULL) {
2370        m = c->FindVirtualMethod(name, sig);
2371      }
2372      if (m == NULL) {
2373        LOG(return_errors ? ERROR : FATAL) << "Failed to register native method "
2374            << PrettyDescriptor(c) << "." << name << sig;
2375        ThrowNoSuchMethodError(soa, c, name, sig, "static or non-static");
2376        return JNI_ERR;
2377      } else if (!m->IsNative()) {
2378        LOG(return_errors ? ERROR : FATAL) << "Failed to register non-native method "
2379            << PrettyDescriptor(c) << "." << name << sig
2380            << " as native";
2381        ThrowNoSuchMethodError(soa, c, name, sig, "native");
2382        return JNI_ERR;
2383      }
2384
2385      VLOG(jni) << "[Registering JNI native method " << PrettyMethod(m) << "]";
2386
2387      m->RegisterNative(soa.Self(), methods[i].fnPtr);
2388    }
2389    return JNI_OK;
2390  }
2391
2392  static jint UnregisterNatives(JNIEnv* env, jclass java_class) {
2393    CHECK_NON_NULL_ARGUMENT(UnregisterNatives, java_class);
2394    ScopedObjectAccess soa(env);
2395    Class* c = soa.Decode<Class*>(java_class);
2396
2397    VLOG(jni) << "[Unregistering JNI native methods for " << PrettyClass(c) << "]";
2398
2399    for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
2400      ArtMethod* m = c->GetDirectMethod(i);
2401      if (m->IsNative()) {
2402        m->UnregisterNative(soa.Self());
2403      }
2404    }
2405    for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
2406      ArtMethod* m = c->GetVirtualMethod(i);
2407      if (m->IsNative()) {
2408        m->UnregisterNative(soa.Self());
2409      }
2410    }
2411
2412    return JNI_OK;
2413  }
2414
2415  static jint MonitorEnter(JNIEnv* env, jobject java_object)
2416      EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) {
2417    CHECK_NON_NULL_ARGUMENT(MonitorEnter, java_object);
2418    ScopedObjectAccess soa(env);
2419    Object* o = soa.Decode<Object*>(java_object);
2420    o->MonitorEnter(soa.Self());
2421    if (soa.Self()->IsExceptionPending()) {
2422      return JNI_ERR;
2423    }
2424    soa.Env()->monitors.Add(o);
2425    return JNI_OK;
2426  }
2427
2428  static jint MonitorExit(JNIEnv* env, jobject java_object)
2429      UNLOCK_FUNCTION(monitor_lock_) {
2430    CHECK_NON_NULL_ARGUMENT(MonitorExit, java_object);
2431    ScopedObjectAccess soa(env);
2432    Object* o = soa.Decode<Object*>(java_object);
2433    o->MonitorExit(soa.Self());
2434    if (soa.Self()->IsExceptionPending()) {
2435      return JNI_ERR;
2436    }
2437    soa.Env()->monitors.Remove(o);
2438    return JNI_OK;
2439  }
2440
2441  static jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
2442    CHECK_NON_NULL_ARGUMENT(GetJavaVM, vm);
2443    Runtime* runtime = Runtime::Current();
2444    if (runtime != NULL) {
2445      *vm = runtime->GetJavaVM();
2446    } else {
2447      *vm = NULL;
2448    }
2449    return (*vm != NULL) ? JNI_OK : JNI_ERR;
2450  }
2451
2452  static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
2453    if (capacity < 0) {
2454      JniAbortF("NewDirectByteBuffer", "negative buffer capacity: %lld", capacity);
2455    }
2456    if (address == NULL && capacity != 0) {
2457      JniAbortF("NewDirectByteBuffer", "non-zero capacity for NULL pointer: %lld", capacity);
2458    }
2459
2460    // At the moment, the Java side is limited to 32 bits.
2461    CHECK_LE(reinterpret_cast<uintptr_t>(address), 0xffffffff);
2462    CHECK_LE(capacity, 0xffffffff);
2463    jlong address_arg = reinterpret_cast<jlong>(address);
2464    jint capacity_arg = static_cast<jint>(capacity);
2465
2466    jobject result = env->NewObject(WellKnownClasses::java_nio_DirectByteBuffer,
2467                                    WellKnownClasses::java_nio_DirectByteBuffer_init,
2468                                    address_arg, capacity_arg);
2469    return static_cast<JNIEnvExt*>(env)->self->IsExceptionPending() ? NULL : result;
2470  }
2471
2472  static void* GetDirectBufferAddress(JNIEnv* env, jobject java_buffer) {
2473    return reinterpret_cast<void*>(env->GetLongField(java_buffer, WellKnownClasses::java_nio_DirectByteBuffer_effectiveDirectAddress));
2474  }
2475
2476  static jlong GetDirectBufferCapacity(JNIEnv* env, jobject java_buffer) {
2477    return static_cast<jlong>(env->GetIntField(java_buffer, WellKnownClasses::java_nio_DirectByteBuffer_capacity));
2478  }
2479
2480  static jobjectRefType GetObjectRefType(JNIEnv* env, jobject java_object) {
2481    CHECK_NON_NULL_ARGUMENT(GetObjectRefType, java_object);
2482
2483    // Do we definitely know what kind of reference this is?
2484    IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
2485    IndirectRefKind kind = GetIndirectRefKind(ref);
2486    switch (kind) {
2487    case kLocal:
2488      if (static_cast<JNIEnvExt*>(env)->locals.Get(ref) != kInvalidIndirectRefObject) {
2489        return JNILocalRefType;
2490      }
2491      return JNIInvalidRefType;
2492    case kGlobal:
2493      return JNIGlobalRefType;
2494    case kWeakGlobal:
2495      return JNIWeakGlobalRefType;
2496    case kSirtOrInvalid:
2497      // Is it in a stack IRT?
2498      if (static_cast<JNIEnvExt*>(env)->self->SirtContains(java_object)) {
2499        return JNILocalRefType;
2500      }
2501
2502      if (!static_cast<JNIEnvExt*>(env)->vm->work_around_app_jni_bugs) {
2503        return JNIInvalidRefType;
2504      }
2505
2506      // If we're handing out direct pointers, check whether it's a direct pointer
2507      // to a local reference.
2508      {
2509        ScopedObjectAccess soa(env);
2510        if (soa.Decode<Object*>(java_object) == reinterpret_cast<Object*>(java_object)) {
2511          if (soa.Env()->locals.ContainsDirectPointer(reinterpret_cast<Object*>(java_object))) {
2512            return JNILocalRefType;
2513          }
2514        }
2515      }
2516      return JNIInvalidRefType;
2517    }
2518    LOG(FATAL) << "IndirectRefKind[" << kind << "]";
2519    return JNIInvalidRefType;
2520  }
2521
2522 private:
2523  static jint EnsureLocalCapacity(JNIEnv* env, jint desired_capacity,
2524                                  const char* caller) {
2525    // TODO: we should try to expand the table if necessary.
2526    if (desired_capacity < 0 || desired_capacity > static_cast<jint>(kLocalsMax)) {
2527      LOG(ERROR) << "Invalid capacity given to " << caller << ": " << desired_capacity;
2528      return JNI_ERR;
2529    }
2530    // TODO: this isn't quite right, since "capacity" includes holes.
2531    size_t capacity = static_cast<JNIEnvExt*>(env)->locals.Capacity();
2532    bool okay = (static_cast<jint>(kLocalsMax - capacity) >= desired_capacity);
2533    if (!okay) {
2534      ScopedObjectAccess soa(env);
2535      soa.Self()->ThrowOutOfMemoryError(caller);
2536    }
2537    return okay ? JNI_OK : JNI_ERR;
2538  }
2539
2540  template<typename JniT, typename ArtT>
2541  static JniT NewPrimitiveArray(const ScopedObjectAccess& soa, jsize length)
2542      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2543    if (length < 0) {
2544      JniAbortF("NewPrimitiveArray", "negative array length: %d", length);
2545    }
2546    ArtT* result = ArtT::Alloc(soa.Self(), length);
2547    return soa.AddLocalReference<JniT>(result);
2548  }
2549
2550  template <typename ArrayT, typename CArrayT, typename ArtArrayT>
2551  static CArrayT GetPrimitiveArray(ScopedObjectAccess& soa, ArrayT java_array,
2552                                   jboolean* is_copy)
2553      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2554    ArtArrayT* array = soa.Decode<ArtArrayT*>(java_array);
2555    PinPrimitiveArray(soa, array);
2556    if (is_copy != NULL) {
2557      *is_copy = JNI_FALSE;
2558    }
2559    return array->GetData();
2560  }
2561
2562  template <typename ArrayT>
2563  static void ReleasePrimitiveArray(JNIEnv* env, ArrayT java_array, jint mode) {
2564    if (mode != JNI_COMMIT) {
2565      ScopedObjectAccess soa(env);
2566      Array* array = soa.Decode<Array*>(java_array);
2567      UnpinPrimitiveArray(soa, array);
2568    }
2569  }
2570
2571  template <typename JavaArrayT, typename JavaT, typename ArrayT>
2572  static void GetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array,
2573                                      jsize start, jsize length, JavaT* buf)
2574      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2575    CHECK_NON_NULL_ARGUMENT(GetPrimitiveArrayRegion, java_array);
2576    ArrayT* array = soa.Decode<ArrayT*>(java_array);
2577    if (start < 0 || length < 0 || start + length > array->GetLength()) {
2578      ThrowAIOOBE(soa, array, start, length, "src");
2579    } else {
2580      CHECK_NON_NULL_MEMCPY_ARGUMENT(GetStringRegion, length, buf);
2581      JavaT* data = array->GetData();
2582      memcpy(buf, data + start, length * sizeof(JavaT));
2583    }
2584  }
2585
2586  template <typename JavaArrayT, typename JavaT, typename ArrayT>
2587  static void SetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array,
2588                                      jsize start, jsize length, const JavaT* buf)
2589      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2590    CHECK_NON_NULL_ARGUMENT(SetPrimitiveArrayRegion, java_array);
2591    ArrayT* array = soa.Decode<ArrayT*>(java_array);
2592    if (start < 0 || length < 0 || start + length > array->GetLength()) {
2593      ThrowAIOOBE(soa, array, start, length, "dst");
2594    } else {
2595      CHECK_NON_NULL_MEMCPY_ARGUMENT(GetStringRegion, length, buf);
2596      JavaT* data = array->GetData();
2597      memcpy(data + start, buf, length * sizeof(JavaT));
2598    }
2599  }
2600};
2601
2602const JNINativeInterface gJniNativeInterface = {
2603  NULL,  // reserved0.
2604  NULL,  // reserved1.
2605  NULL,  // reserved2.
2606  NULL,  // reserved3.
2607  JNI::GetVersion,
2608  JNI::DefineClass,
2609  JNI::FindClass,
2610  JNI::FromReflectedMethod,
2611  JNI::FromReflectedField,
2612  JNI::ToReflectedMethod,
2613  JNI::GetSuperclass,
2614  JNI::IsAssignableFrom,
2615  JNI::ToReflectedField,
2616  JNI::Throw,
2617  JNI::ThrowNew,
2618  JNI::ExceptionOccurred,
2619  JNI::ExceptionDescribe,
2620  JNI::ExceptionClear,
2621  JNI::FatalError,
2622  JNI::PushLocalFrame,
2623  JNI::PopLocalFrame,
2624  JNI::NewGlobalRef,
2625  JNI::DeleteGlobalRef,
2626  JNI::DeleteLocalRef,
2627  JNI::IsSameObject,
2628  JNI::NewLocalRef,
2629  JNI::EnsureLocalCapacity,
2630  JNI::AllocObject,
2631  JNI::NewObject,
2632  JNI::NewObjectV,
2633  JNI::NewObjectA,
2634  JNI::GetObjectClass,
2635  JNI::IsInstanceOf,
2636  JNI::GetMethodID,
2637  JNI::CallObjectMethod,
2638  JNI::CallObjectMethodV,
2639  JNI::CallObjectMethodA,
2640  JNI::CallBooleanMethod,
2641  JNI::CallBooleanMethodV,
2642  JNI::CallBooleanMethodA,
2643  JNI::CallByteMethod,
2644  JNI::CallByteMethodV,
2645  JNI::CallByteMethodA,
2646  JNI::CallCharMethod,
2647  JNI::CallCharMethodV,
2648  JNI::CallCharMethodA,
2649  JNI::CallShortMethod,
2650  JNI::CallShortMethodV,
2651  JNI::CallShortMethodA,
2652  JNI::CallIntMethod,
2653  JNI::CallIntMethodV,
2654  JNI::CallIntMethodA,
2655  JNI::CallLongMethod,
2656  JNI::CallLongMethodV,
2657  JNI::CallLongMethodA,
2658  JNI::CallFloatMethod,
2659  JNI::CallFloatMethodV,
2660  JNI::CallFloatMethodA,
2661  JNI::CallDoubleMethod,
2662  JNI::CallDoubleMethodV,
2663  JNI::CallDoubleMethodA,
2664  JNI::CallVoidMethod,
2665  JNI::CallVoidMethodV,
2666  JNI::CallVoidMethodA,
2667  JNI::CallNonvirtualObjectMethod,
2668  JNI::CallNonvirtualObjectMethodV,
2669  JNI::CallNonvirtualObjectMethodA,
2670  JNI::CallNonvirtualBooleanMethod,
2671  JNI::CallNonvirtualBooleanMethodV,
2672  JNI::CallNonvirtualBooleanMethodA,
2673  JNI::CallNonvirtualByteMethod,
2674  JNI::CallNonvirtualByteMethodV,
2675  JNI::CallNonvirtualByteMethodA,
2676  JNI::CallNonvirtualCharMethod,
2677  JNI::CallNonvirtualCharMethodV,
2678  JNI::CallNonvirtualCharMethodA,
2679  JNI::CallNonvirtualShortMethod,
2680  JNI::CallNonvirtualShortMethodV,
2681  JNI::CallNonvirtualShortMethodA,
2682  JNI::CallNonvirtualIntMethod,
2683  JNI::CallNonvirtualIntMethodV,
2684  JNI::CallNonvirtualIntMethodA,
2685  JNI::CallNonvirtualLongMethod,
2686  JNI::CallNonvirtualLongMethodV,
2687  JNI::CallNonvirtualLongMethodA,
2688  JNI::CallNonvirtualFloatMethod,
2689  JNI::CallNonvirtualFloatMethodV,
2690  JNI::CallNonvirtualFloatMethodA,
2691  JNI::CallNonvirtualDoubleMethod,
2692  JNI::CallNonvirtualDoubleMethodV,
2693  JNI::CallNonvirtualDoubleMethodA,
2694  JNI::CallNonvirtualVoidMethod,
2695  JNI::CallNonvirtualVoidMethodV,
2696  JNI::CallNonvirtualVoidMethodA,
2697  JNI::GetFieldID,
2698  JNI::GetObjectField,
2699  JNI::GetBooleanField,
2700  JNI::GetByteField,
2701  JNI::GetCharField,
2702  JNI::GetShortField,
2703  JNI::GetIntField,
2704  JNI::GetLongField,
2705  JNI::GetFloatField,
2706  JNI::GetDoubleField,
2707  JNI::SetObjectField,
2708  JNI::SetBooleanField,
2709  JNI::SetByteField,
2710  JNI::SetCharField,
2711  JNI::SetShortField,
2712  JNI::SetIntField,
2713  JNI::SetLongField,
2714  JNI::SetFloatField,
2715  JNI::SetDoubleField,
2716  JNI::GetStaticMethodID,
2717  JNI::CallStaticObjectMethod,
2718  JNI::CallStaticObjectMethodV,
2719  JNI::CallStaticObjectMethodA,
2720  JNI::CallStaticBooleanMethod,
2721  JNI::CallStaticBooleanMethodV,
2722  JNI::CallStaticBooleanMethodA,
2723  JNI::CallStaticByteMethod,
2724  JNI::CallStaticByteMethodV,
2725  JNI::CallStaticByteMethodA,
2726  JNI::CallStaticCharMethod,
2727  JNI::CallStaticCharMethodV,
2728  JNI::CallStaticCharMethodA,
2729  JNI::CallStaticShortMethod,
2730  JNI::CallStaticShortMethodV,
2731  JNI::CallStaticShortMethodA,
2732  JNI::CallStaticIntMethod,
2733  JNI::CallStaticIntMethodV,
2734  JNI::CallStaticIntMethodA,
2735  JNI::CallStaticLongMethod,
2736  JNI::CallStaticLongMethodV,
2737  JNI::CallStaticLongMethodA,
2738  JNI::CallStaticFloatMethod,
2739  JNI::CallStaticFloatMethodV,
2740  JNI::CallStaticFloatMethodA,
2741  JNI::CallStaticDoubleMethod,
2742  JNI::CallStaticDoubleMethodV,
2743  JNI::CallStaticDoubleMethodA,
2744  JNI::CallStaticVoidMethod,
2745  JNI::CallStaticVoidMethodV,
2746  JNI::CallStaticVoidMethodA,
2747  JNI::GetStaticFieldID,
2748  JNI::GetStaticObjectField,
2749  JNI::GetStaticBooleanField,
2750  JNI::GetStaticByteField,
2751  JNI::GetStaticCharField,
2752  JNI::GetStaticShortField,
2753  JNI::GetStaticIntField,
2754  JNI::GetStaticLongField,
2755  JNI::GetStaticFloatField,
2756  JNI::GetStaticDoubleField,
2757  JNI::SetStaticObjectField,
2758  JNI::SetStaticBooleanField,
2759  JNI::SetStaticByteField,
2760  JNI::SetStaticCharField,
2761  JNI::SetStaticShortField,
2762  JNI::SetStaticIntField,
2763  JNI::SetStaticLongField,
2764  JNI::SetStaticFloatField,
2765  JNI::SetStaticDoubleField,
2766  JNI::NewString,
2767  JNI::GetStringLength,
2768  JNI::GetStringChars,
2769  JNI::ReleaseStringChars,
2770  JNI::NewStringUTF,
2771  JNI::GetStringUTFLength,
2772  JNI::GetStringUTFChars,
2773  JNI::ReleaseStringUTFChars,
2774  JNI::GetArrayLength,
2775  JNI::NewObjectArray,
2776  JNI::GetObjectArrayElement,
2777  JNI::SetObjectArrayElement,
2778  JNI::NewBooleanArray,
2779  JNI::NewByteArray,
2780  JNI::NewCharArray,
2781  JNI::NewShortArray,
2782  JNI::NewIntArray,
2783  JNI::NewLongArray,
2784  JNI::NewFloatArray,
2785  JNI::NewDoubleArray,
2786  JNI::GetBooleanArrayElements,
2787  JNI::GetByteArrayElements,
2788  JNI::GetCharArrayElements,
2789  JNI::GetShortArrayElements,
2790  JNI::GetIntArrayElements,
2791  JNI::GetLongArrayElements,
2792  JNI::GetFloatArrayElements,
2793  JNI::GetDoubleArrayElements,
2794  JNI::ReleaseBooleanArrayElements,
2795  JNI::ReleaseByteArrayElements,
2796  JNI::ReleaseCharArrayElements,
2797  JNI::ReleaseShortArrayElements,
2798  JNI::ReleaseIntArrayElements,
2799  JNI::ReleaseLongArrayElements,
2800  JNI::ReleaseFloatArrayElements,
2801  JNI::ReleaseDoubleArrayElements,
2802  JNI::GetBooleanArrayRegion,
2803  JNI::GetByteArrayRegion,
2804  JNI::GetCharArrayRegion,
2805  JNI::GetShortArrayRegion,
2806  JNI::GetIntArrayRegion,
2807  JNI::GetLongArrayRegion,
2808  JNI::GetFloatArrayRegion,
2809  JNI::GetDoubleArrayRegion,
2810  JNI::SetBooleanArrayRegion,
2811  JNI::SetByteArrayRegion,
2812  JNI::SetCharArrayRegion,
2813  JNI::SetShortArrayRegion,
2814  JNI::SetIntArrayRegion,
2815  JNI::SetLongArrayRegion,
2816  JNI::SetFloatArrayRegion,
2817  JNI::SetDoubleArrayRegion,
2818  JNI::RegisterNatives,
2819  JNI::UnregisterNatives,
2820  JNI::MonitorEnter,
2821  JNI::MonitorExit,
2822  JNI::GetJavaVM,
2823  JNI::GetStringRegion,
2824  JNI::GetStringUTFRegion,
2825  JNI::GetPrimitiveArrayCritical,
2826  JNI::ReleasePrimitiveArrayCritical,
2827  JNI::GetStringCritical,
2828  JNI::ReleaseStringCritical,
2829  JNI::NewWeakGlobalRef,
2830  JNI::DeleteWeakGlobalRef,
2831  JNI::ExceptionCheck,
2832  JNI::NewDirectByteBuffer,
2833  JNI::GetDirectBufferAddress,
2834  JNI::GetDirectBufferCapacity,
2835  JNI::GetObjectRefType,
2836};
2837
2838JNIEnvExt::JNIEnvExt(Thread* self, JavaVMExt* vm)
2839    : self(self),
2840      vm(vm),
2841      local_ref_cookie(IRT_FIRST_SEGMENT),
2842      locals(kLocalsInitial, kLocalsMax, kLocal),
2843      check_jni(false),
2844      critical(false),
2845      monitors("monitors", kMonitorsInitial, kMonitorsMax) {
2846  functions = unchecked_functions = &gJniNativeInterface;
2847  if (vm->check_jni) {
2848    SetCheckJniEnabled(true);
2849  }
2850  // The JniEnv local reference values must be at a consistent offset or else cross-compilation
2851  // errors will ensue.
2852  CHECK_EQ(JNIEnvExt::LocalRefCookieOffset().Int32Value(), 12);
2853  CHECK_EQ(JNIEnvExt::SegmentStateOffset().Int32Value(), 16);
2854}
2855
2856JNIEnvExt::~JNIEnvExt() {
2857}
2858
2859void JNIEnvExt::SetCheckJniEnabled(bool enabled) {
2860  check_jni = enabled;
2861  functions = enabled ? GetCheckJniNativeInterface() : &gJniNativeInterface;
2862}
2863
2864void JNIEnvExt::DumpReferenceTables(std::ostream& os) {
2865  locals.Dump(os);
2866  monitors.Dump(os);
2867}
2868
2869void JNIEnvExt::PushFrame(int /*capacity*/) {
2870  // TODO: take 'capacity' into account.
2871  stacked_local_ref_cookies.push_back(local_ref_cookie);
2872  local_ref_cookie = locals.GetSegmentState();
2873}
2874
2875void JNIEnvExt::PopFrame() {
2876  locals.SetSegmentState(local_ref_cookie);
2877  local_ref_cookie = stacked_local_ref_cookies.back();
2878  stacked_local_ref_cookies.pop_back();
2879}
2880
2881Offset JNIEnvExt::SegmentStateOffset() {
2882  return Offset(OFFSETOF_MEMBER(JNIEnvExt, locals) +
2883                IndirectReferenceTable::SegmentStateOffset().Int32Value());
2884}
2885
2886// JNI Invocation interface.
2887
2888extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
2889  const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
2890  if (IsBadJniVersion(args->version)) {
2891    LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
2892    return JNI_EVERSION;
2893  }
2894  Runtime::Options options;
2895  for (int i = 0; i < args->nOptions; ++i) {
2896    JavaVMOption* option = &args->options[i];
2897    options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
2898  }
2899  bool ignore_unrecognized = args->ignoreUnrecognized;
2900  if (!Runtime::Create(options, ignore_unrecognized)) {
2901    return JNI_ERR;
2902  }
2903  Runtime* runtime = Runtime::Current();
2904  bool started = runtime->Start();
2905  if (!started) {
2906    delete Thread::Current()->GetJniEnv();
2907    delete runtime->GetJavaVM();
2908    LOG(WARNING) << "CreateJavaVM failed";
2909    return JNI_ERR;
2910  }
2911  *p_env = Thread::Current()->GetJniEnv();
2912  *p_vm = runtime->GetJavaVM();
2913  return JNI_OK;
2914}
2915
2916extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize, jsize* vm_count) {
2917  Runtime* runtime = Runtime::Current();
2918  if (runtime == NULL) {
2919    *vm_count = 0;
2920  } else {
2921    *vm_count = 1;
2922    vms[0] = runtime->GetJavaVM();
2923  }
2924  return JNI_OK;
2925}
2926
2927// Historically unsupported.
2928extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* /*vm_args*/) {
2929  return JNI_ERR;
2930}
2931
2932class JII {
2933 public:
2934  static jint DestroyJavaVM(JavaVM* vm) {
2935    if (vm == NULL) {
2936      return JNI_ERR;
2937    }
2938    JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2939    delete raw_vm->runtime;
2940    return JNI_OK;
2941  }
2942
2943  static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2944    return JII_AttachCurrentThread(vm, p_env, thr_args, false);
2945  }
2946
2947  static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2948    return JII_AttachCurrentThread(vm, p_env, thr_args, true);
2949  }
2950
2951  static jint DetachCurrentThread(JavaVM* vm) {
2952    if (vm == NULL || Thread::Current() == NULL) {
2953      return JNI_ERR;
2954    }
2955    JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
2956    Runtime* runtime = raw_vm->runtime;
2957    runtime->DetachCurrentThread();
2958    return JNI_OK;
2959  }
2960
2961  static jint GetEnv(JavaVM* vm, void** env, jint version) {
2962    // GetEnv always returns a JNIEnv* for the most current supported JNI version,
2963    // and unlike other calls that take a JNI version doesn't care if you supply
2964    // JNI_VERSION_1_1, which we don't otherwise support.
2965    if (IsBadJniVersion(version) && version != JNI_VERSION_1_1) {
2966      LOG(ERROR) << "Bad JNI version passed to GetEnv: " << version;
2967      return JNI_EVERSION;
2968    }
2969    if (vm == NULL || env == NULL) {
2970      return JNI_ERR;
2971    }
2972    Thread* thread = Thread::Current();
2973    if (thread == NULL) {
2974      *env = NULL;
2975      return JNI_EDETACHED;
2976    }
2977    *env = thread->GetJniEnv();
2978    return JNI_OK;
2979  }
2980};
2981
2982const JNIInvokeInterface gJniInvokeInterface = {
2983  NULL,  // reserved0
2984  NULL,  // reserved1
2985  NULL,  // reserved2
2986  JII::DestroyJavaVM,
2987  JII::AttachCurrentThread,
2988  JII::DetachCurrentThread,
2989  JII::GetEnv,
2990  JII::AttachCurrentThreadAsDaemon
2991};
2992
2993JavaVMExt::JavaVMExt(Runtime* runtime, Runtime::ParsedOptions* options)
2994    : runtime(runtime),
2995      check_jni_abort_hook(NULL),
2996      check_jni_abort_hook_data(NULL),
2997      check_jni(false),
2998      force_copy(false),  // TODO: add a way to enable this
2999      trace(options->jni_trace_),
3000      work_around_app_jni_bugs(false),
3001      pins_lock("JNI pin table lock", kPinTableLock),
3002      pin_table("pin table", kPinTableInitial, kPinTableMax),
3003      globals_lock("JNI global reference table lock"),
3004      globals(gGlobalsInitial, gGlobalsMax, kGlobal),
3005      libraries_lock("JNI shared libraries map lock", kLoadLibraryLock),
3006      libraries(new Libraries),
3007      weak_globals_lock_("JNI weak global reference table lock"),
3008      weak_globals_(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal),
3009      allow_new_weak_globals_(true),
3010      weak_globals_add_condition_("weak globals add condition", weak_globals_lock_) {
3011  functions = unchecked_functions = &gJniInvokeInterface;
3012  if (options->check_jni_) {
3013    SetCheckJniEnabled(true);
3014  }
3015}
3016
3017JavaVMExt::~JavaVMExt() {
3018  delete libraries;
3019}
3020
3021jweak JavaVMExt::AddWeakGlobalReference(Thread* self, mirror::Object* obj) {
3022  if (obj == nullptr) {
3023    return nullptr;
3024  }
3025  MutexLock mu(self, weak_globals_lock_);
3026  while (UNLIKELY(!allow_new_weak_globals_)) {
3027    weak_globals_add_condition_.WaitHoldingLocks(self);
3028  }
3029  IndirectRef ref = weak_globals_.Add(IRT_FIRST_SEGMENT, obj);
3030  return reinterpret_cast<jweak>(ref);
3031}
3032
3033void JavaVMExt::DeleteWeakGlobalRef(Thread* self, jweak obj) {
3034  MutexLock mu(self, weak_globals_lock_);
3035  if (!weak_globals_.Remove(IRT_FIRST_SEGMENT, obj)) {
3036    LOG(WARNING) << "JNI WARNING: DeleteWeakGlobalRef(" << obj << ") "
3037                 << "failed to find entry";
3038  }
3039}
3040
3041void JavaVMExt::SetCheckJniEnabled(bool enabled) {
3042  check_jni = enabled;
3043  functions = enabled ? GetCheckJniInvokeInterface() : &gJniInvokeInterface;
3044}
3045
3046void JavaVMExt::DumpForSigQuit(std::ostream& os) {
3047  os << "JNI: CheckJNI is " << (check_jni ? "on" : "off");
3048  if (force_copy) {
3049    os << " (with forcecopy)";
3050  }
3051  os << "; workarounds are " << (work_around_app_jni_bugs ? "on" : "off");
3052  Thread* self = Thread::Current();
3053  {
3054    MutexLock mu(self, pins_lock);
3055    os << "; pins=" << pin_table.Size();
3056  }
3057  {
3058    ReaderMutexLock mu(self, globals_lock);
3059    os << "; globals=" << globals.Capacity();
3060  }
3061  {
3062    MutexLock mu(self, weak_globals_lock_);
3063    if (weak_globals_.Capacity() > 0) {
3064      os << " (plus " << weak_globals_.Capacity() << " weak)";
3065    }
3066  }
3067  os << '\n';
3068
3069  {
3070    MutexLock mu(self, libraries_lock);
3071    os << "Libraries: " << Dumpable<Libraries>(*libraries) << " (" << libraries->size() << ")\n";
3072  }
3073}
3074
3075void JavaVMExt::DisallowNewWeakGlobals() {
3076  MutexLock mu(Thread::Current(), weak_globals_lock_);
3077  allow_new_weak_globals_ = false;
3078}
3079
3080void JavaVMExt::AllowNewWeakGlobals() {
3081  Thread* self = Thread::Current();
3082  MutexLock mu(self, weak_globals_lock_);
3083  allow_new_weak_globals_ = true;
3084  weak_globals_add_condition_.Broadcast(self);
3085}
3086
3087void JavaVMExt::SweepWeakGlobals(IsMarkedTester is_marked, void* arg) {
3088  MutexLock mu(Thread::Current(), weak_globals_lock_);
3089  for (const Object** entry : weak_globals_) {
3090    if (!is_marked(*entry, arg)) {
3091      *entry = kClearedJniWeakGlobal;
3092    }
3093  }
3094}
3095
3096mirror::Object* JavaVMExt::DecodeWeakGlobal(Thread* self, IndirectRef ref) {
3097  MutexLock mu(self, weak_globals_lock_);
3098  while (UNLIKELY(!allow_new_weak_globals_)) {
3099    weak_globals_add_condition_.WaitHoldingLocks(self);
3100  }
3101  return const_cast<mirror::Object*>(weak_globals_.Get(ref));
3102}
3103
3104void JavaVMExt::DumpReferenceTables(std::ostream& os) {
3105  Thread* self = Thread::Current();
3106  {
3107    ReaderMutexLock mu(self, globals_lock);
3108    globals.Dump(os);
3109  }
3110  {
3111    MutexLock mu(self, weak_globals_lock_);
3112    weak_globals_.Dump(os);
3113  }
3114  {
3115    MutexLock mu(self, pins_lock);
3116    pin_table.Dump(os);
3117  }
3118}
3119
3120bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_loader,
3121                                  std::string& detail) {
3122  detail.clear();
3123
3124  // See if we've already loaded this library.  If we have, and the class loader
3125  // matches, return successfully without doing anything.
3126  // TODO: for better results we should canonicalize the pathname (or even compare
3127  // inodes). This implementation is fine if everybody is using System.loadLibrary.
3128  SharedLibrary* library;
3129  Thread* self = Thread::Current();
3130  {
3131    // TODO: move the locking (and more of this logic) into Libraries.
3132    MutexLock mu(self, libraries_lock);
3133    library = libraries->Get(path);
3134  }
3135  if (library != NULL) {
3136    if (library->GetClassLoader() != class_loader) {
3137      // The library will be associated with class_loader. The JNI
3138      // spec says we can't load the same library into more than one
3139      // class loader.
3140      StringAppendF(&detail, "Shared library \"%s\" already opened by "
3141          "ClassLoader %p; can't open in ClassLoader %p",
3142          path.c_str(), library->GetClassLoader(), class_loader);
3143      LOG(WARNING) << detail;
3144      return false;
3145    }
3146    VLOG(jni) << "[Shared library \"" << path << "\" already loaded in "
3147              << "ClassLoader " << class_loader << "]";
3148    if (!library->CheckOnLoadResult()) {
3149      StringAppendF(&detail, "JNI_OnLoad failed on a previous attempt "
3150          "to load \"%s\"", path.c_str());
3151      return false;
3152    }
3153    return true;
3154  }
3155
3156  // Open the shared library.  Because we're using a full path, the system
3157  // doesn't have to search through LD_LIBRARY_PATH.  (It may do so to
3158  // resolve this library's dependencies though.)
3159
3160  // Failures here are expected when java.library.path has several entries
3161  // and we have to hunt for the lib.
3162
3163  // Below we dlopen but there is no paired dlclose, this would be necessary if we supported
3164  // class unloading. Libraries will only be unloaded when the reference count (incremented by
3165  // dlopen) becomes zero from dlclose.
3166
3167  // This can execute slowly for a large library on a busy system, so we
3168  // want to switch from kRunnable while it executes.  This allows the GC to ignore us.
3169  self->TransitionFromRunnableToSuspended(kWaitingForJniOnLoad);
3170  void* handle = dlopen(path.empty() ? NULL : path.c_str(), RTLD_LAZY);
3171  self->TransitionFromSuspendedToRunnable();
3172
3173  VLOG(jni) << "[Call to dlopen(\"" << path << "\", RTLD_LAZY) returned " << handle << "]";
3174
3175  if (handle == NULL) {
3176    detail = dlerror();
3177    LOG(ERROR) << "dlopen(\"" << path << "\", RTLD_LAZY) failed: " << detail;
3178    return false;
3179  }
3180
3181  // Create a new entry.
3182  // TODO: move the locking (and more of this logic) into Libraries.
3183  bool created_library = false;
3184  {
3185    MutexLock mu(self, libraries_lock);
3186    library = libraries->Get(path);
3187    if (library == NULL) {  // We won race to get libraries_lock
3188      library = new SharedLibrary(path, handle, class_loader);
3189      libraries->Put(path, library);
3190      created_library = true;
3191    }
3192  }
3193  if (!created_library) {
3194    LOG(INFO) << "WOW: we lost a race to add shared library: "
3195        << "\"" << path << "\" ClassLoader=" << class_loader;
3196    return library->CheckOnLoadResult();
3197  }
3198
3199  VLOG(jni) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]";
3200
3201  bool was_successful = false;
3202  void* sym = dlsym(handle, "JNI_OnLoad");
3203  if (sym == NULL) {
3204    VLOG(jni) << "[No JNI_OnLoad found in \"" << path << "\"]";
3205    was_successful = true;
3206  } else {
3207    // Call JNI_OnLoad.  We have to override the current class
3208    // loader, which will always be "null" since the stuff at the
3209    // top of the stack is around Runtime.loadLibrary().  (See
3210    // the comments in the JNI FindClass function.)
3211    typedef int (*JNI_OnLoadFn)(JavaVM*, void*);
3212    JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
3213    ClassLoader* old_class_loader = self->GetClassLoaderOverride();
3214    self->SetClassLoaderOverride(class_loader);
3215
3216    int version = 0;
3217    {
3218      ScopedThreadStateChange tsc(self, kNative);
3219      VLOG(jni) << "[Calling JNI_OnLoad in \"" << path << "\"]";
3220      version = (*jni_on_load)(this, NULL);
3221    }
3222
3223    self->SetClassLoaderOverride(old_class_loader);
3224
3225    if (version == JNI_ERR) {
3226      StringAppendF(&detail, "JNI_ERR returned from JNI_OnLoad in \"%s\"", path.c_str());
3227    } else if (IsBadJniVersion(version)) {
3228      StringAppendF(&detail, "Bad JNI version returned from JNI_OnLoad in \"%s\": %d",
3229                    path.c_str(), version);
3230      // It's unwise to call dlclose() here, but we can mark it
3231      // as bad and ensure that future load attempts will fail.
3232      // We don't know how far JNI_OnLoad got, so there could
3233      // be some partially-initialized stuff accessible through
3234      // newly-registered native method calls.  We could try to
3235      // unregister them, but that doesn't seem worthwhile.
3236    } else {
3237      was_successful = true;
3238    }
3239    VLOG(jni) << "[Returned " << (was_successful ? "successfully" : "failure")
3240              << " from JNI_OnLoad in \"" << path << "\"]";
3241  }
3242
3243  library->SetResult(was_successful);
3244  return was_successful;
3245}
3246
3247void* JavaVMExt::FindCodeForNativeMethod(ArtMethod* m) {
3248  CHECK(m->IsNative());
3249
3250  Class* c = m->GetDeclaringClass();
3251
3252  // If this is a static method, it could be called before the class
3253  // has been initialized.
3254  if (m->IsStatic()) {
3255    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
3256      return NULL;
3257    }
3258  } else {
3259    CHECK(c->IsInitializing()) << c->GetStatus() << " " << PrettyMethod(m);
3260  }
3261
3262  std::string detail;
3263  void* native_method;
3264  Thread* self = Thread::Current();
3265  {
3266    MutexLock mu(self, libraries_lock);
3267    native_method = libraries->FindNativeMethod(m, detail);
3268  }
3269  // Throwing can cause libraries_lock to be reacquired.
3270  if (native_method == NULL) {
3271    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
3272    self->ThrowNewException(throw_location, "Ljava/lang/UnsatisfiedLinkError;", detail.c_str());
3273  }
3274  return native_method;
3275}
3276
3277void JavaVMExt::VisitRoots(RootVisitor* visitor, void* arg) {
3278  Thread* self = Thread::Current();
3279  {
3280    ReaderMutexLock mu(self, globals_lock);
3281    globals.VisitRoots(visitor, arg);
3282  }
3283  {
3284    MutexLock mu(self, pins_lock);
3285    pin_table.VisitRoots(visitor, arg);
3286  }
3287  // The weak_globals table is visited by the GC itself (because it mutates the table).
3288}
3289
3290void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINativeMethod* methods,
3291                           jint method_count) {
3292  ScopedLocalRef<jclass> c(env, env->FindClass(jni_class_name));
3293  if (c.get() == NULL) {
3294    LOG(FATAL) << "Couldn't find class: " << jni_class_name;
3295  }
3296  JNI::RegisterNativeMethods(env, c.get(), methods, method_count, false);
3297}
3298
3299}  // namespace art
3300
3301std::ostream& operator<<(std::ostream& os, const jobjectRefType& rhs) {
3302  switch (rhs) {
3303  case JNIInvalidRefType:
3304    os << "JNIInvalidRefType";
3305    return os;
3306  case JNILocalRefType:
3307    os << "JNILocalRefType";
3308    return os;
3309  case JNIGlobalRefType:
3310    os << "JNIGlobalRefType";
3311    return os;
3312  case JNIWeakGlobalRefType:
3313    os << "JNIWeakGlobalRefType";
3314    return os;
3315  default:
3316    LOG(FATAL) << "jobjectRefType[" << static_cast<int>(rhs) << "]";
3317    return os;
3318  }
3319}
3320