/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "jni_internal.h"

#define ATRACE_TAG ATRACE_TAG_DALVIK

#include <cutils/trace.h>
#include <dlfcn.h>

#include "art_method.h"
#include "base/dumpable.h"
#include "base/mutex.h"
#include "base/stl_util.h"
#include "check_jni.h"
#include "dex_file-inl.h"
#include "fault_handler.h"
#include "indirect_reference_table-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "nativebridge/native_bridge.h"
#include "nativeloader/native_loader.h"
#include "java_vm_ext.h"
#include "parsed_options.h"
#include "runtime-inl.h"
#include "runtime_options.h"
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change.h"
#include "thread-inl.h"
#include "thread_list.h"

namespace art {

static size_t gGlobalsInitial = 512;  // Arbitrary.
static size_t gGlobalsMax = 51200;  // Arbitrary sanity check. (Must fit in 16 bits.)

static const size_t kWeakGlobalsInitial = 16;  // Arbitrary.
static const size_t kWeakGlobalsMax = 51200;  // Arbitrary sanity check. (Must fit in 16 bits.)

static bool IsBadJniVersion(int version) {
  // We don't support JNI_VERSION_1_1. These are the only other valid versions.
  return version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 && version != JNI_VERSION_1_6;
}

class SharedLibrary {
 public:
  SharedLibrary(JNIEnv* env, Thread* self, const std::string& path, void* handle,
                jobject class_loader, void* class_loader_allocator)
      : path_(path),
        handle_(handle),
        needs_native_bridge_(false),
        class_loader_(env->NewWeakGlobalRef(class_loader)),
        class_loader_allocator_(class_loader_allocator),
        jni_on_load_lock_("JNI_OnLoad lock"),
        jni_on_load_cond_("JNI_OnLoad condition variable", jni_on_load_lock_),
        jni_on_load_thread_id_(self->GetThreadId()),
        jni_on_load_result_(kPending) {
    CHECK(class_loader_allocator_ != nullptr);
  }

  ~SharedLibrary() {
    Thread* self = Thread::Current();
    if (self != nullptr) {
      self->GetJniEnv()->DeleteWeakGlobalRef(class_loader_);
    }
  }

  jweak GetClassLoader() const {
    return class_loader_;
  }

  const void* GetClassLoaderAllocator() const {
    return class_loader_allocator_;
  }

  const std::string& GetPath() const {
    return path_;
  }

  /*
   * Check the result of an earlier call to JNI_OnLoad on this library.
   * If the call has not yet finished in another thread, wait for it.
   */
  bool CheckOnLoadResult()
      REQUIRES(!jni_on_load_lock_) {
    Thread* self = Thread::Current();
    bool okay;
    {
      MutexLock mu(self, jni_on_load_lock_);

      if (jni_on_load_thread_id_ == self->GetThreadId()) {
        // Check this so we don't end up waiting for ourselves.  We need to return "true" so the
        // caller can continue.
        LOG(INFO) << *self << " recursive attempt to load library " << "\"" << path_ << "\"";
        okay = true;
      } else {
        while (jni_on_load_result_ == kPending) {
          VLOG(jni) << "[" << *self << " waiting for \"" << path_ << "\" " << "JNI_OnLoad...]";
          jni_on_load_cond_.Wait(self);
        }

        okay = (jni_on_load_result_ == kOkay);
        VLOG(jni) << "[Earlier JNI_OnLoad for \"" << path_ << "\" "
            << (okay ? "succeeded" : "failed") << "]";
      }
    }
    return okay;
  }

  void SetResult(bool result) REQUIRES(!jni_on_load_lock_) {
    Thread* self = Thread::Current();
    MutexLock mu(self, jni_on_load_lock_);

    jni_on_load_result_ = result ? kOkay : kFailed;
    jni_on_load_thread_id_ = 0;

    // Broadcast a wakeup to anybody sleeping on the condition variable.
    jni_on_load_cond_.Broadcast(self);
  }

  void SetNeedsNativeBridge() {
    needs_native_bridge_ = true;
  }

  bool NeedsNativeBridge() const {
    return needs_native_bridge_;
  }

  void* FindSymbol(const std::string& symbol_name, const char* shorty = nullptr) {
    return NeedsNativeBridge()
        ? FindSymbolWithNativeBridge(symbol_name.c_str(), shorty)
        : FindSymbolWithoutNativeBridge(symbol_name.c_str());
  }

  void* FindSymbolWithoutNativeBridge(const std::string& symbol_name) {
    CHECK(!NeedsNativeBridge());

    return dlsym(handle_, symbol_name.c_str());
  }

  void* FindSymbolWithNativeBridge(const std::string& symbol_name, const char* shorty) {
    CHECK(NeedsNativeBridge());

    uint32_t len = 0;
    return android::NativeBridgeGetTrampoline(handle_, symbol_name.c_str(), shorty, len);
  }

 private:
  enum JNI_OnLoadState {
    kPending,
    kFailed,
    kOkay,
  };

  // Path to library "/system/lib/libjni.so".
  const std::string path_;

  // The void* returned by dlopen(3).
  void* const handle_;

  // True if a native bridge is required.
  bool needs_native_bridge_;

  // The ClassLoader this library is associated with, a weak global JNI reference that is
  // created/deleted with the scope of the library.
  const jweak class_loader_;
  // Used to do equality check on class loaders so we can avoid decoding the weak root and read
  // barriers that mess with class unloading.
  const void* class_loader_allocator_;

  // Guards remaining items.
  Mutex jni_on_load_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
  // Wait for JNI_OnLoad in other thread.
  ConditionVariable jni_on_load_cond_ GUARDED_BY(jni_on_load_lock_);
  // Recursive invocation guard.
  uint32_t jni_on_load_thread_id_ GUARDED_BY(jni_on_load_lock_);
  // Result of earlier JNI_OnLoad call.
  JNI_OnLoadState jni_on_load_result_ GUARDED_BY(jni_on_load_lock_);
};

// This exists mainly to keep implementation details out of the header file.
class Libraries {
 public:
  Libraries() {
  }

  ~Libraries() {
    STLDeleteValues(&libraries_);
  }

  // NO_THREAD_SAFETY_ANALYSIS since this may be called from Dumpable. Dumpable can't be annotated
  // properly due to the template. The caller should be holding the jni_libraries_lock_.
  void Dump(std::ostream& os) const NO_THREAD_SAFETY_ANALYSIS {
    Locks::jni_libraries_lock_->AssertHeld(Thread::Current());
    bool first = true;
    for (const auto& library : libraries_) {
      if (!first) {
        os << ' ';
      }
      first = false;
      os << library.first;
    }
  }

  size_t size() const REQUIRES(Locks::jni_libraries_lock_) {
    return libraries_.size();
  }

  SharedLibrary* Get(const std::string& path) REQUIRES(Locks::jni_libraries_lock_) {
    auto it = libraries_.find(path);
    return (it == libraries_.end()) ? nullptr : it->second;
  }

  void Put(const std::string& path, SharedLibrary* library)
      REQUIRES(Locks::jni_libraries_lock_) {
    libraries_.Put(path, library);
  }

  // See section 11.3 "Linking Native Methods" of the JNI spec.
  void* FindNativeMethod(ArtMethod* m, std::string& detail)
      REQUIRES(Locks::jni_libraries_lock_)
      SHARED_REQUIRES(Locks::mutator_lock_) {
    std::string jni_short_name(JniShortName(m));
    std::string jni_long_name(JniLongName(m));
    mirror::ClassLoader* const declaring_class_loader = m->GetDeclaringClass()->GetClassLoader();
    ScopedObjectAccessUnchecked soa(Thread::Current());
    void* const declaring_class_loader_allocator =
        Runtime::Current()->GetClassLinker()->GetAllocatorForClassLoader(declaring_class_loader);
    CHECK(declaring_class_loader_allocator != nullptr);
    for (const auto& lib : libraries_) {
      SharedLibrary* const library = lib.second;
      // Use the allocator address for class loader equality to avoid unnecessary weak root decode.
      if (library->GetClassLoaderAllocator() != declaring_class_loader_allocator) {
        // We only search libraries loaded by the appropriate ClassLoader.
        continue;
      }
      // Try the short name then the long name...
      const char* shorty = library->NeedsNativeBridge()
          ? m->GetShorty()
          : nullptr;
      void* fn = library->FindSymbol(jni_short_name, shorty);
      if (fn == nullptr) {
        fn = library->FindSymbol(jni_long_name, shorty);
      }
      if (fn != nullptr) {
        VLOG(jni) << "[Found native code for " << PrettyMethod(m)
                  << " in \"" << library->GetPath() << "\"]";
        return fn;
      }
    }
    detail += "No implementation found for ";
    detail += PrettyMethod(m);
    detail += " (tried " + jni_short_name + " and " + jni_long_name + ")";
    LOG(ERROR) << detail;
    return nullptr;
  }

  // Unload native libraries with cleared class loaders.
  void UnloadNativeLibraries()
      REQUIRES(!Locks::jni_libraries_lock_)
      SHARED_REQUIRES(Locks::mutator_lock_) {
    ScopedObjectAccessUnchecked soa(Thread::Current());
    typedef void (*JNI_OnUnloadFn)(JavaVM*, void*);
    std::vector<JNI_OnUnloadFn> unload_functions;
    {
      MutexLock mu(soa.Self(), *Locks::jni_libraries_lock_);
      for (auto it = libraries_.begin(); it != libraries_.end(); ) {
        SharedLibrary* const library = it->second;
        // If class loader is null then it was unloaded, call JNI_OnUnload.
        const jweak class_loader = library->GetClassLoader();
        // If class_loader is a null jobject then it is the boot class loader. We should not unload
        // the native libraries of the boot class loader.
        if (class_loader != nullptr &&
            soa.Self()->IsJWeakCleared(class_loader)) {
          void* const sym = library->FindSymbol("JNI_OnUnload", nullptr);
          if (sym == nullptr) {
            VLOG(jni) << "[No JNI_OnUnload found in \"" << library->GetPath() << "\"]";
          } else {
            VLOG(jni) << "[JNI_OnUnload found for \"" << library->GetPath() << "\"]";
            JNI_OnUnloadFn jni_on_unload = reinterpret_cast<JNI_OnUnloadFn>(sym);
            unload_functions.push_back(jni_on_unload);
          }
          delete library;
          it = libraries_.erase(it);
        } else {
          ++it;
        }
      }
    }
    // Do this without holding the jni libraries lock to prevent possible deadlocks.
    for (JNI_OnUnloadFn fn : unload_functions) {
      VLOG(jni) << "Calling JNI_OnUnload";
      (*fn)(soa.Vm(), nullptr);
    }
  }

 private:
  AllocationTrackingSafeMap<std::string, SharedLibrary*, kAllocatorTagJNILibraries> libraries_
      GUARDED_BY(Locks::jni_libraries_lock_);
};

class JII {
 public:
  static jint DestroyJavaVM(JavaVM* vm) {
    if (vm == nullptr) {
      return JNI_ERR;
    }
    JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
    delete raw_vm->GetRuntime();
    return JNI_OK;
  }

  static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
    return AttachCurrentThreadInternal(vm, p_env, thr_args, false);
  }

  static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
    return AttachCurrentThreadInternal(vm, p_env, thr_args, true);
  }

  static jint DetachCurrentThread(JavaVM* vm) {
    if (vm == nullptr || Thread::Current() == nullptr) {
      return JNI_ERR;
    }
    JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
    Runtime* runtime = raw_vm->GetRuntime();
    runtime->DetachCurrentThread();
    return JNI_OK;
  }

  static jint GetEnv(JavaVM* vm, void** env, jint version) {
    // GetEnv always returns a JNIEnv* for the most current supported JNI version,
    // and unlike other calls that take a JNI version doesn't care if you supply
    // JNI_VERSION_1_1, which we don't otherwise support.
    if (IsBadJniVersion(version) && version != JNI_VERSION_1_1) {
      LOG(ERROR) << "Bad JNI version passed to GetEnv: " << version;
      return JNI_EVERSION;
    }
    if (vm == nullptr || env == nullptr) {
      return JNI_ERR;
    }
    Thread* thread = Thread::Current();
    if (thread == nullptr) {
      *env = nullptr;
      return JNI_EDETACHED;
    }
    *env = thread->GetJniEnv();
    return JNI_OK;
  }

 private:
  static jint AttachCurrentThreadInternal(JavaVM* vm, JNIEnv** p_env, void* raw_args, bool as_daemon) {
    if (vm == nullptr || p_env == nullptr) {
      return JNI_ERR;
    }

    // Return immediately if we're already attached.
    Thread* self = Thread::Current();
    if (self != nullptr) {
      *p_env = self->GetJniEnv();
      return JNI_OK;
    }

    Runtime* runtime = reinterpret_cast<JavaVMExt*>(vm)->GetRuntime();

    // No threads allowed in zygote mode.
    if (runtime->IsZygote()) {
      LOG(ERROR) << "Attempt to attach a thread in the zygote";
      return JNI_ERR;
    }

    JavaVMAttachArgs* args = static_cast<JavaVMAttachArgs*>(raw_args);
    const char* thread_name = nullptr;
    jobject thread_group = nullptr;
    if (args != nullptr) {
      if (IsBadJniVersion(args->version)) {
        LOG(ERROR) << "Bad JNI version passed to "
                   << (as_daemon ? "AttachCurrentThreadAsDaemon" : "AttachCurrentThread") << ": "
                   << args->version;
        return JNI_EVERSION;
      }
      thread_name = args->name;
      thread_group = args->group;
    }

    if (!runtime->AttachCurrentThread(thread_name, as_daemon, thread_group,
                                      !runtime->IsAotCompiler())) {
      *p_env = nullptr;
      return JNI_ERR;
    } else {
      *p_env = Thread::Current()->GetJniEnv();
      return JNI_OK;
    }
  }
};

const JNIInvokeInterface gJniInvokeInterface = {
  nullptr,  // reserved0
  nullptr,  // reserved1
  nullptr,  // reserved2
  JII::DestroyJavaVM,
  JII::AttachCurrentThread,
  JII::DetachCurrentThread,
  JII::GetEnv,
  JII::AttachCurrentThreadAsDaemon
};

JavaVMExt::JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options)
    : runtime_(runtime),
      check_jni_abort_hook_(nullptr),
      check_jni_abort_hook_data_(nullptr),
      check_jni_(false),  // Initialized properly in the constructor body below.
      force_copy_(runtime_options.Exists(RuntimeArgumentMap::JniOptsForceCopy)),
      tracing_enabled_(runtime_options.Exists(RuntimeArgumentMap::JniTrace)
                       || VLOG_IS_ON(third_party_jni)),
      trace_(runtime_options.GetOrDefault(RuntimeArgumentMap::JniTrace)),
      globals_lock_("JNI global reference table lock"),
      globals_(gGlobalsInitial, gGlobalsMax, kGlobal),
      libraries_(new Libraries),
      unchecked_functions_(&gJniInvokeInterface),
      weak_globals_lock_("JNI weak global reference table lock", kJniWeakGlobalsLock),
      weak_globals_(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal),
      allow_accessing_weak_globals_(true),
      weak_globals_add_condition_("weak globals add condition", weak_globals_lock_) {
  functions = unchecked_functions_;
  SetCheckJniEnabled(runtime_options.Exists(RuntimeArgumentMap::CheckJni));
}

JavaVMExt::~JavaVMExt() {
}

void JavaVMExt::JniAbort(const char* jni_function_name, const char* msg) {
  Thread* self = Thread::Current();
  ScopedObjectAccess soa(self);
  ArtMethod* current_method = self->GetCurrentMethod(nullptr);

  std::ostringstream os;
  os << "JNI DETECTED ERROR IN APPLICATION: " << msg;

  if (jni_function_name != nullptr) {
    os << "\n    in call to " << jni_function_name;
  }
  // TODO: is this useful given that we're about to dump the calling thread's stack?
  if (current_method != nullptr) {
    os << "\n    from " << PrettyMethod(current_method);
  }
  os << "\n";
  self->Dump(os);

  if (check_jni_abort_hook_ != nullptr) {
    check_jni_abort_hook_(check_jni_abort_hook_data_, os.str());
  } else {
    // Ensure that we get a native stack trace for this thread.
    ScopedThreadSuspension sts(self, kNative);
    LOG(FATAL) << os.str();
    UNREACHABLE();
  }
}

void JavaVMExt::JniAbortV(const char* jni_function_name, const char* fmt, va_list ap) {
  std::string msg;
  StringAppendV(&msg, fmt, ap);
  JniAbort(jni_function_name, msg.c_str());
}

void JavaVMExt::JniAbortF(const char* jni_function_name, const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  JniAbortV(jni_function_name, fmt, args);
  va_end(args);
}

bool JavaVMExt::ShouldTrace(ArtMethod* method) {
  // Fast where no tracing is enabled.
  if (trace_.empty() && !VLOG_IS_ON(third_party_jni)) {
    return false;
  }
  // Perform checks based on class name.
  StringPiece class_name(method->GetDeclaringClassDescriptor());
  if (!trace_.empty() && class_name.find(trace_) != std::string::npos) {
    return true;
  }
  if (!VLOG_IS_ON(third_party_jni)) {
    return false;
  }
  // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
  // like part of Android.
  static const char* gBuiltInPrefixes[] = {
      "Landroid/",
      "Lcom/android/",
      "Lcom/google/android/",
      "Ldalvik/",
      "Ljava/",
      "Ljavax/",
      "Llibcore/",
      "Lorg/apache/harmony/",
  };
  for (size_t i = 0; i < arraysize(gBuiltInPrefixes); ++i) {
    if (class_name.starts_with(gBuiltInPrefixes[i])) {
      return false;
    }
  }
  return true;
}

jobject JavaVMExt::AddGlobalRef(Thread* self, mirror::Object* obj) {
  // Check for null after decoding the object to handle cleared weak globals.
  if (obj == nullptr) {
    return nullptr;
  }
  WriterMutexLock mu(self, globals_lock_);
  IndirectRef ref = globals_.Add(IRT_FIRST_SEGMENT, obj);
  return reinterpret_cast<jobject>(ref);
}

jweak JavaVMExt::AddWeakGlobalRef(Thread* self, mirror::Object* obj) {
  if (obj == nullptr) {
    return nullptr;
  }
  MutexLock mu(self, weak_globals_lock_);
  while (UNLIKELY(!MayAccessWeakGlobals(self))) {
    weak_globals_add_condition_.WaitHoldingLocks(self);
  }
  IndirectRef ref = weak_globals_.Add(IRT_FIRST_SEGMENT, obj);
  return reinterpret_cast<jweak>(ref);
}

void JavaVMExt::DeleteGlobalRef(Thread* self, jobject obj) {
  if (obj == nullptr) {
    return;
  }
  WriterMutexLock mu(self, globals_lock_);
  if (!globals_.Remove(IRT_FIRST_SEGMENT, obj)) {
    LOG(WARNING) << "JNI WARNING: DeleteGlobalRef(" << obj << ") "
                 << "failed to find entry";
  }
}

void JavaVMExt::DeleteWeakGlobalRef(Thread* self, jweak obj) {
  if (obj == nullptr) {
    return;
  }
  MutexLock mu(self, weak_globals_lock_);
  if (!weak_globals_.Remove(IRT_FIRST_SEGMENT, obj)) {
    LOG(WARNING) << "JNI WARNING: DeleteWeakGlobalRef(" << obj << ") "
                 << "failed to find entry";
  }
}

static void ThreadEnableCheckJni(Thread* thread, void* arg) {
  bool* check_jni = reinterpret_cast<bool*>(arg);
  thread->GetJniEnv()->SetCheckJniEnabled(*check_jni);
}

bool JavaVMExt::SetCheckJniEnabled(bool enabled) {
  bool old_check_jni = check_jni_;
  check_jni_ = enabled;
  functions = enabled ? GetCheckJniInvokeInterface() : unchecked_functions_;
  MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
  runtime_->GetThreadList()->ForEach(ThreadEnableCheckJni, &check_jni_);
  return old_check_jni;
}

void JavaVMExt::DumpForSigQuit(std::ostream& os) {
  os << "JNI: CheckJNI is " << (check_jni_ ? "on" : "off");
  if (force_copy_) {
    os << " (with forcecopy)";
  }
  Thread* self = Thread::Current();
  {
    ReaderMutexLock mu(self, globals_lock_);
    os << "; globals=" << globals_.Capacity();
  }
  {
    MutexLock mu(self, weak_globals_lock_);
    if (weak_globals_.Capacity() > 0) {
      os << " (plus " << weak_globals_.Capacity() << " weak)";
    }
  }
  os << '\n';

  {
    MutexLock mu(self, *Locks::jni_libraries_lock_);
    os << "Libraries: " << Dumpable<Libraries>(*libraries_) << " (" << libraries_->size() << ")\n";
  }
}

void JavaVMExt::DisallowNewWeakGlobals() {
  CHECK(!kUseReadBarrier);
  Thread* const self = Thread::Current();
  MutexLock mu(self, weak_globals_lock_);
  // DisallowNewWeakGlobals is only called by CMS during the pause. It is required to have the
  // mutator lock exclusively held so that we don't have any threads in the middle of
  // DecodeWeakGlobal.
  Locks::mutator_lock_->AssertExclusiveHeld(self);
  allow_accessing_weak_globals_.StoreSequentiallyConsistent(false);
}

void JavaVMExt::AllowNewWeakGlobals() {
  CHECK(!kUseReadBarrier);
  Thread* self = Thread::Current();
  MutexLock mu(self, weak_globals_lock_);
  allow_accessing_weak_globals_.StoreSequentiallyConsistent(true);
  weak_globals_add_condition_.Broadcast(self);
}

void JavaVMExt::BroadcastForNewWeakGlobals() {
  CHECK(kUseReadBarrier);
  Thread* self = Thread::Current();
  MutexLock mu(self, weak_globals_lock_);
  weak_globals_add_condition_.Broadcast(self);
}

mirror::Object* JavaVMExt::DecodeGlobal(IndirectRef ref) {
  return globals_.SynchronizedGet(ref);
}

void JavaVMExt::UpdateGlobal(Thread* self, IndirectRef ref, mirror::Object* result) {
  WriterMutexLock mu(self, globals_lock_);
  globals_.Update(ref, result);
}

inline bool JavaVMExt::MayAccessWeakGlobals(Thread* self) const {
  return MayAccessWeakGlobalsUnlocked(self);
}

inline bool JavaVMExt::MayAccessWeakGlobalsUnlocked(Thread* self) const {
  DCHECK(self != nullptr);
  return kUseReadBarrier ?
      self->GetWeakRefAccessEnabled() :
      allow_accessing_weak_globals_.LoadSequentiallyConsistent();
}

mirror::Object* JavaVMExt::DecodeWeakGlobal(Thread* self, IndirectRef ref) {
  // It is safe to access GetWeakRefAccessEnabled without the lock since CC uses checkpoints to call
  // SetWeakRefAccessEnabled, and the other collectors only modify allow_accessing_weak_globals_
  // when the mutators are paused.
  // This only applies in the case where MayAccessWeakGlobals goes from false to true. In the other
  // case, it may be racy, this is benign since DecodeWeakGlobalLocked does the correct behavior
  // if MayAccessWeakGlobals is false.
  DCHECK_EQ(GetIndirectRefKind(ref), kWeakGlobal);
  if (LIKELY(MayAccessWeakGlobalsUnlocked(self))) {
    return weak_globals_.SynchronizedGet(ref);
  }
  MutexLock mu(self, weak_globals_lock_);
  return DecodeWeakGlobalLocked(self, ref);
}

mirror::Object* JavaVMExt::DecodeWeakGlobalLocked(Thread* self, IndirectRef ref) {
  if (kDebugLocking) {
    weak_globals_lock_.AssertHeld(self);
  }
  while (UNLIKELY(!MayAccessWeakGlobals(self))) {
    weak_globals_add_condition_.WaitHoldingLocks(self);
  }
  return weak_globals_.Get(ref);
}

mirror::Object* JavaVMExt::DecodeWeakGlobalDuringShutdown(Thread* self, IndirectRef ref) {
  DCHECK_EQ(GetIndirectRefKind(ref), kWeakGlobal);
  DCHECK(Runtime::Current()->IsShuttingDown(self));
  if (self != nullptr) {
    return DecodeWeakGlobal(self, ref);
  }
  // self can be null during a runtime shutdown. ~Runtime()->~ClassLinker()->DecodeWeakGlobal().
  if (!kUseReadBarrier) {
    DCHECK(allow_accessing_weak_globals_.LoadSequentiallyConsistent());
  }
  return weak_globals_.SynchronizedGet(ref);
}

bool JavaVMExt::IsWeakGlobalCleared(Thread* self, IndirectRef ref) {
  DCHECK_EQ(GetIndirectRefKind(ref), kWeakGlobal);
  MutexLock mu(self, weak_globals_lock_);
  while (UNLIKELY(!MayAccessWeakGlobals(self))) {
    weak_globals_add_condition_.WaitHoldingLocks(self);
  }
  // When just checking a weak ref has been cleared, avoid triggering the read barrier in decode
  // (DecodeWeakGlobal) so that we won't accidentally mark the object alive. Since the cleared
  // sentinel is a non-moving object, we can compare the ref to it without the read barrier and
  // decide if it's cleared.
  return Runtime::Current()->IsClearedJniWeakGlobal(weak_globals_.Get<kWithoutReadBarrier>(ref));
}

void JavaVMExt::UpdateWeakGlobal(Thread* self, IndirectRef ref, mirror::Object* result) {
  MutexLock mu(self, weak_globals_lock_);
  weak_globals_.Update(ref, result);
}

void JavaVMExt::DumpReferenceTables(std::ostream& os) {
  Thread* self = Thread::Current();
  {
    ReaderMutexLock mu(self, globals_lock_);
    globals_.Dump(os);
  }
  {
    MutexLock mu(self, weak_globals_lock_);
    weak_globals_.Dump(os);
  }
}

void JavaVMExt::UnloadNativeLibraries() {
  libraries_.get()->UnloadNativeLibraries();
}

bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject class_loader,
                                  jstring library_path, jstring permitted_path,
                                  std::string* error_msg) {
  error_msg->clear();

  // See if we've already loaded this library.  If we have, and the class loader
  // matches, return successfully without doing anything.
  // TODO: for better results we should canonicalize the pathname (or even compare
  // inodes). This implementation is fine if everybody is using System.loadLibrary.
  SharedLibrary* library;
  Thread* self = Thread::Current();
  {
    // TODO: move the locking (and more of this logic) into Libraries.
    MutexLock mu(self, *Locks::jni_libraries_lock_);
    library = libraries_->Get(path);
  }
  void* class_loader_allocator = nullptr;
  {
    ScopedObjectAccess soa(env);
    // As the incoming class loader is reachable/alive during the call of this function,
    // it's okay to decode it without worrying about unexpectedly marking it alive.
    mirror::ClassLoader* loader = soa.Decode<mirror::ClassLoader*>(class_loader);
    class_loader_allocator =
        Runtime::Current()->GetClassLinker()->GetAllocatorForClassLoader(loader);
    CHECK(class_loader_allocator != nullptr);
  }
  if (library != nullptr) {
    // Use the allocator pointers for class loader equality to avoid unnecessary weak root decode.
    if (library->GetClassLoaderAllocator() != class_loader_allocator) {
      // The library will be associated with class_loader. The JNI
      // spec says we can't load the same library into more than one
      // class loader.
      StringAppendF(error_msg, "Shared library \"%s\" already opened by "
          "ClassLoader %p; can't open in ClassLoader %p",
          path.c_str(), library->GetClassLoader(), class_loader);
      LOG(WARNING) << error_msg;
      return false;
    }
    VLOG(jni) << "[Shared library \"" << path << "\" already loaded in "
              << " ClassLoader " << class_loader << "]";
    if (!library->CheckOnLoadResult()) {
      StringAppendF(error_msg, "JNI_OnLoad failed on a previous attempt "
          "to load \"%s\"", path.c_str());
      return false;
    }
    return true;
  }

  // Open the shared library.  Because we're using a full path, the system
  // doesn't have to search through LD_LIBRARY_PATH.  (It may do so to
  // resolve this library's dependencies though.)

  // Failures here are expected when java.library.path has several entries
  // and we have to hunt for the lib.

  // Below we dlopen but there is no paired dlclose, this would be necessary if we supported
  // class unloading. Libraries will only be unloaded when the reference count (incremented by
  // dlopen) becomes zero from dlclose.

  Locks::mutator_lock_->AssertNotHeld(self);
  const char* path_str = path.empty() ? nullptr : path.c_str();
  void* handle = android::OpenNativeLibrary(env, runtime_->GetTargetSdkVersion(),
                                            path_str, class_loader, library_path, permitted_path);
  bool needs_native_bridge = false;
  if (handle == nullptr) {
    if (android::NativeBridgeIsSupported(path_str)) {
      handle = android::NativeBridgeLoadLibrary(path_str, RTLD_NOW);
      needs_native_bridge = true;
    }
  }

  VLOG(jni) << "[Call to dlopen(\"" << path << "\", RTLD_NOW) returned " << handle << "]";

  if (handle == nullptr) {
    *error_msg = dlerror();
    VLOG(jni) << "dlopen(\"" << path << "\", RTLD_NOW) failed: " << *error_msg;
    return false;
  }

  if (env->ExceptionCheck() == JNI_TRUE) {
    LOG(ERROR) << "Unexpected exception:";
    env->ExceptionDescribe();
    env->ExceptionClear();
  }
  // Create a new entry.
  // TODO: move the locking (and more of this logic) into Libraries.
  bool created_library = false;
  {
    // Create SharedLibrary ahead of taking the libraries lock to maintain lock ordering.
    std::unique_ptr<SharedLibrary> new_library(
        new SharedLibrary(env, self, path, handle, class_loader, class_loader_allocator));
    MutexLock mu(self, *Locks::jni_libraries_lock_);
    library = libraries_->Get(path);
    if (library == nullptr) {  // We won race to get libraries_lock.
      library = new_library.release();
      libraries_->Put(path, library);
      created_library = true;
    }
  }
  if (!created_library) {
    LOG(INFO) << "WOW: we lost a race to add shared library: "
        << "\"" << path << "\" ClassLoader=" << class_loader;
    return library->CheckOnLoadResult();
  }
  VLOG(jni) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]";

  bool was_successful = false;
  void* sym;
  if (needs_native_bridge) {
    library->SetNeedsNativeBridge();
  }
  sym = library->FindSymbol("JNI_OnLoad", nullptr);
  if (sym == nullptr) {
    VLOG(jni) << "[No JNI_OnLoad found in \"" << path << "\"]";
    was_successful = true;
  } else {
    // Call JNI_OnLoad.  We have to override the current class
    // loader, which will always be "null" since the stuff at the
    // top of the stack is around Runtime.loadLibrary().  (See
    // the comments in the JNI FindClass function.)
    ScopedLocalRef<jobject> old_class_loader(env, env->NewLocalRef(self->GetClassLoaderOverride()));
    self->SetClassLoaderOverride(class_loader);

    VLOG(jni) << "[Calling JNI_OnLoad in \"" << path << "\"]";
    typedef int (*JNI_OnLoadFn)(JavaVM*, void*);
    JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
    int version = (*jni_on_load)(this, nullptr);

    if (runtime_->GetTargetSdkVersion() != 0 && runtime_->GetTargetSdkVersion() <= 21) {
      fault_manager.EnsureArtActionInFrontOfSignalChain();
    }

    self->SetClassLoaderOverride(old_class_loader.get());

    if (version == JNI_ERR) {
      StringAppendF(error_msg, "JNI_ERR returned from JNI_OnLoad in \"%s\"", path.c_str());
    } else if (IsBadJniVersion(version)) {
      StringAppendF(error_msg, "Bad JNI version returned from JNI_OnLoad in \"%s\": %d",
                    path.c_str(), version);
      // It's unwise to call dlclose() here, but we can mark it
      // as bad and ensure that future load attempts will fail.
      // We don't know how far JNI_OnLoad got, so there could
      // be some partially-initialized stuff accessible through
      // newly-registered native method calls.  We could try to
      // unregister them, but that doesn't seem worthwhile.
    } else {
      was_successful = true;
    }
    VLOG(jni) << "[Returned " << (was_successful ? "successfully" : "failure")
              << " from JNI_OnLoad in \"" << path << "\"]";
  }

  library->SetResult(was_successful);
  return was_successful;
}

void* JavaVMExt::FindCodeForNativeMethod(ArtMethod* m) {
  CHECK(m->IsNative());
  mirror::Class* c = m->GetDeclaringClass();
  // If this is a static method, it could be called before the class has been initialized.
  CHECK(c->IsInitializing()) << c->GetStatus() << " " << PrettyMethod(m);
  std::string detail;
  void* native_method;
  Thread* self = Thread::Current();
  {
    MutexLock mu(self, *Locks::jni_libraries_lock_);
    native_method = libraries_->FindNativeMethod(m, detail);
  }
  // Throwing can cause libraries_lock to be reacquired.
  if (native_method == nullptr) {
    self->ThrowNewException("Ljava/lang/UnsatisfiedLinkError;", detail.c_str());
  }
  return native_method;
}

void JavaVMExt::SweepJniWeakGlobals(IsMarkedVisitor* visitor) {
  MutexLock mu(Thread::Current(), weak_globals_lock_);
  Runtime* const runtime = Runtime::Current();
  for (auto* entry : weak_globals_) {
    // Need to skip null here to distinguish between null entries and cleared weak ref entries.
    if (!entry->IsNull()) {
      // Since this is called by the GC, we don't need a read barrier.
      mirror::Object* obj = entry->Read<kWithoutReadBarrier>();
      mirror::Object* new_obj = visitor->IsMarked(obj);
      if (new_obj == nullptr) {
        new_obj = runtime->GetClearedJniWeakGlobal();
      }
      *entry = GcRoot<mirror::Object>(new_obj);
    }
  }
}

void JavaVMExt::TrimGlobals() {
  WriterMutexLock mu(Thread::Current(), globals_lock_);
  globals_.Trim();
}

void JavaVMExt::VisitRoots(RootVisitor* visitor) {
  Thread* self = Thread::Current();
  ReaderMutexLock mu(self, globals_lock_);
  globals_.VisitRoots(visitor, RootInfo(kRootJNIGlobal));
  // The weak_globals table is visited by the GC itself (because it mutates the table).
}

// JNI Invocation interface.

extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  ATRACE_BEGIN(__FUNCTION__);
  const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
  if (IsBadJniVersion(args->version)) {
    LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
    ATRACE_END();
    return JNI_EVERSION;
  }
  RuntimeOptions options;
  for (int i = 0; i < args->nOptions; ++i) {
    JavaVMOption* option = &args->options[i];
    options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
  }
  bool ignore_unrecognized = args->ignoreUnrecognized;
  if (!Runtime::Create(options, ignore_unrecognized)) {
    ATRACE_END();
    return JNI_ERR;
  }
  Runtime* runtime = Runtime::Current();
  bool started = runtime->Start();
  if (!started) {
    delete Thread::Current()->GetJniEnv();
    delete runtime->GetJavaVM();
    LOG(WARNING) << "CreateJavaVM failed";
    ATRACE_END();
    return JNI_ERR;
  }
  *p_env = Thread::Current()->GetJniEnv();
  *p_vm = runtime->GetJavaVM();
  ATRACE_END();
  return JNI_OK;
}

extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms_buf, jsize buf_len, jsize* vm_count) {
  Runtime* runtime = Runtime::Current();
  if (runtime == nullptr || buf_len == 0) {
    *vm_count = 0;
  } else {
    *vm_count = 1;
    vms_buf[0] = runtime->GetJavaVM();
  }
  return JNI_OK;
}

// Historically unsupported.
extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* /*vm_args*/) {
  return JNI_ERR;
}

}  // namespace art
