/*
 * 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 "java_vm_ext-inl.h"

#include <dlfcn.h>
#include <string_view>

#include "android-base/stringprintf.h"

#include "art_method-inl.h"
#include "base/dumpable.h"
#include "base/mutex-inl.h"
#include "base/sdk_version.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "check_jni.h"
#include "dex/dex_file-inl.h"
#include "entrypoints/entrypoint_utils-inl.h"
#include "fault_handler.h"
#include "gc/allocation_record.h"
#include "gc/heap.h"
#include "gc_root-inl.h"
#include "indirect_reference_table-inl.h"
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/dex_cache-inl.h"
#include "nativebridge/native_bridge.h"
#include "nativehelper/scoped_local_ref.h"
#include "nativehelper/scoped_utf_chars.h"
#include "nativeloader/native_loader.h"
#include "parsed_options.h"
#include "runtime-inl.h"
#include "runtime_options.h"
#include "scoped_thread_state_change-inl.h"
#include "sigchain.h"
#include "thread-inl.h"
#include "thread_list.h"
#include "ti/agent.h"
#include "well_known_classes-inl.h"

namespace art HIDDEN {

using android::base::StringAppendF;
using android::base::StringAppendV;

// Maximum number of global references (must fit in 16 bits).
static constexpr size_t kGlobalsMax = 51200;

// Maximum number of weak global references (must fit in 16 bits).
static constexpr size_t kWeakGlobalsMax = 51200;

bool JavaVMExt::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,
                bool needs_native_bridge, jobject class_loader, void* class_loader_allocator)
      : path_(path),
        handle_(handle),
        needs_native_bridge_(needs_native_bridge),
        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_);
    }

    char* error_msg = nullptr;
    if (!android::CloseNativeLibrary(handle_, needs_native_bridge_, &error_msg)) {
      LOG(WARNING) << "Error while unloading native library \"" << path_ << "\": " << error_msg;
      android::NativeLoaderFreeErrorMessage(error_msg);
    }
  }

  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(bool needs) {
    needs_native_bridge_ = needs;
  }

  bool NeedsNativeBridge() const {
    return needs_native_bridge_;
  }

  // No mutator lock since dlsym may block for a while if another thread is doing dlopen.
  void* FindSymbol(const std::string& symbol_name,
                   const char* shorty,
                   android::JNICallType jni_call_type) REQUIRES(!Locks::mutator_lock_) {
    return NeedsNativeBridge() ? FindSymbolWithNativeBridge(symbol_name, shorty, jni_call_type) :
                                 FindSymbolWithoutNativeBridge(symbol_name);
  }

  // No mutator lock since dlsym may block for a while if another thread is doing dlopen.
  void* FindSymbolWithoutNativeBridge(const std::string& symbol_name)
      REQUIRES(!Locks::mutator_lock_) {
    CHECK(!NeedsNativeBridge());

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

  void* FindSymbolWithNativeBridge(const std::string& symbol_name,
                                   const char* shorty,
                                   android::JNICallType jni_call_type)
      REQUIRES(!Locks::mutator_lock_) {
    CHECK(NeedsNativeBridge());

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

 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 as this is during runtime shutdown, and we have
  // no thread to lock this with.
  void UnloadBootNativeLibraries(JavaVM* vm) const NO_THREAD_SAFETY_ANALYSIS {
    CHECK(Thread::Current() == nullptr);
    std::vector<SharedLibrary*> unload_libraries;
    for (auto it = libraries_.begin(); it != libraries_.end(); ++it) {
      SharedLibrary* const library = it->second;
      if (library->GetClassLoader() == nullptr) {
        unload_libraries.push_back(library);
      }
    }
    UnloadLibraries(vm, unload_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(Thread* self, ArtMethod* m, std::string* detail, bool can_suspend)
      REQUIRES(!Locks::jni_libraries_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    std::string jni_short_name(m->JniShortName());
    std::string jni_long_name(m->JniLongName());
    const ObjPtr<mirror::ClassLoader> declaring_class_loader =
        m->GetDeclaringClass()->GetClassLoader();
    void* const declaring_class_loader_allocator =
        Runtime::Current()->GetClassLinker()->GetAllocatorForClassLoader(declaring_class_loader);
    CHECK(declaring_class_loader_allocator != nullptr);
    // TODO: Avoid calling GetShorty here to prevent dirtying dex pages?
    const char* shorty = m->GetShorty();
    void* native_code = nullptr;
    android::JNICallType jni_call_type =
        m->IsCriticalNative() ? android::kJNICallTypeCriticalNative : android::kJNICallTypeRegular;
    if (can_suspend) {
      // Go to suspended since dlsym may block for a long time if other threads are using dlopen.
      ScopedThreadSuspension sts(self, ThreadState::kNative);
      native_code = FindNativeMethodInternal(self,
                                             declaring_class_loader_allocator,
                                             shorty,
                                             jni_short_name,
                                             jni_long_name,
                                             jni_call_type);
    } else {
      native_code = FindNativeMethodInternal(self,
                                             declaring_class_loader_allocator,
                                             shorty,
                                             jni_short_name,
                                             jni_long_name,
                                             jni_call_type);
    }
    if (native_code != nullptr) {
      return native_code;
    }
    if (detail != nullptr) {
      *detail += "No implementation found for ";
      *detail += m->PrettyMethod();
      *detail += " (tried " + jni_short_name + " and " + jni_long_name + ")";
      *detail += " - is the library loaded, e.g. System.loadLibrary?";
    }
    return nullptr;
  }

  void* FindNativeMethodInternal(Thread* self,
                                 void* declaring_class_loader_allocator,
                                 const char* shorty,
                                 const std::string& jni_short_name,
                                 const std::string& jni_long_name,
                                 android::JNICallType jni_call_type)
      REQUIRES(!Locks::jni_libraries_lock_) {
    MutexLock mu(self, *Locks::jni_libraries_lock_);
    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* arg_shorty = library->NeedsNativeBridge() ? shorty : nullptr;
      void* fn = library->FindSymbol(jni_short_name, arg_shorty, jni_call_type);
      if (fn == nullptr) {
        fn = library->FindSymbol(jni_long_name, arg_shorty, jni_call_type);
      }
      if (fn != nullptr) {
        VLOG(jni) << "[Found native code for " << jni_long_name
                  << " in \"" << library->GetPath() << "\"]";
        return fn;
      }
    }
    return nullptr;
  }

  // Unload native libraries with cleared class loaders.
  void UnloadNativeLibraries()
      REQUIRES(!Locks::jni_libraries_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    Thread* const self = Thread::Current();
    std::vector<SharedLibrary*> unload_libraries;
    {
      // jni_libraries_lock_ appears to be held long enough that we just retry once, rather than
      // spinning.
      int retries = 0;
      static constexpr int MAX_RETRIES = 5;
      while (!Locks::jni_libraries_lock_->ExclusiveTryLock(self)) {
        if (Runtime::Current()->IsZygote()) {
          // Do not risk deferring to the child processes.
          Locks::jni_libraries_lock_->ExclusiveLock(self);
          break;
        }
        if (++retries > MAX_RETRIES) {
          // We do not want to block indefinitely here, for fear of timeouts. See b/374209523.
          LOG(WARNING) << "Deferring native library unloading due to contention";
          return;
        }
        ScopedTrace("sleep 1 msec for jni_libraries_lock_");
        usleep(1000);
      }
      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 && self->IsJWeakCleared(class_loader)) {
          unload_libraries.push_back(library);
          it = libraries_.erase(it);
        } else {
          ++it;
        }
      }
      Locks::jni_libraries_lock_->ExclusiveUnlock(self);
    }
    ScopedThreadSuspension sts(self, ThreadState::kNative);
    // Do this without holding the jni libraries lock to prevent possible deadlocks.
    UnloadLibraries(self->GetJniEnv()->GetVm(), unload_libraries);
    for (auto library : unload_libraries) {
      delete library;
    }
  }

  static void UnloadLibraries(JavaVM* vm, const std::vector<SharedLibrary*>& libraries) {
    using JNI_OnUnloadFn = void(*)(JavaVM*, void*);
    for (SharedLibrary* library : libraries) {
      void* const sym = library->FindSymbol("JNI_OnUnload", nullptr, android::kJNICallTypeRegular);
      if (sym == nullptr) {
        VLOG(jni) << "[No JNI_OnUnload found in \"" << library->GetPath() << "\"]";
      } else {
        VLOG(jni) << "[JNI_OnUnload found for \"" << library->GetPath() << "\"]: Calling...";
        JNI_OnUnloadFn jni_on_unload = reinterpret_cast<JNI_OnUnloadFn>(sym);
        jni_on_unload(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);

    // Wait for all non-dameon threads to terminate before we start destroying
    // bits of the runtime. Thread list deletion will repeat this in case more
    // threads are created by daemons in the meantime.
    raw_vm->GetRuntime()->GetThreadList()
          ->WaitForOtherNonDaemonThreadsToExit(/*check_no_birth=*/ false);

    delete raw_vm->GetRuntime();
    android::ResetNativeLoader();
    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) {
    if (vm == nullptr || env == nullptr) {
      return JNI_ERR;
    }
    Thread* thread = Thread::Current();
    if (thread == nullptr) {
      *env = nullptr;
      return JNI_EDETACHED;
    }
    JavaVMExt* raw_vm = reinterpret_cast<JavaVMExt*>(vm);
    return raw_vm->HandleGetEnv(env, version);
  }

 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 (JavaVMExt::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_(kGlobal),
      libraries_(new Libraries),
      unchecked_functions_(&gJniInvokeInterface),
      weak_globals_(kWeakGlobal),
      allow_accessing_weak_globals_(true),
      weak_globals_add_condition_("weak globals add condition",
                                  (CHECK(Locks::jni_weak_globals_lock_ != nullptr),
                                   *Locks::jni_weak_globals_lock_)),
      env_hooks_lock_("environment hooks lock", art::kGenericBottomLock),
      env_hooks_(),
      enable_allocation_tracking_delta_(
          runtime_options.GetOrDefault(RuntimeArgumentMap::GlobalRefAllocStackTraceLimit)),
      allocation_tracking_enabled_(false),
      old_allocation_tracking_state_(false) {
  functions = unchecked_functions_;
  SetCheckJniEnabled(runtime_options.Exists(RuntimeArgumentMap::CheckJni) || kIsDebugBuild);
}

bool JavaVMExt::Initialize(std::string* error_msg) {
  return globals_.Initialize(kGlobalsMax, error_msg) &&
         weak_globals_.Initialize(kWeakGlobalsMax, error_msg);
}

JavaVMExt::~JavaVMExt() {
  UnloadBootNativeLibraries();
}

std::unique_ptr<JavaVMExt> JavaVMExt::Create(Runtime* runtime,
                                             const RuntimeArgumentMap& runtime_options,
                                             std::string* error_msg) {
  std::unique_ptr<JavaVMExt> java_vm(new JavaVMExt(runtime, runtime_options));
  if (!java_vm->Initialize(error_msg)) {
    return nullptr;
  }
  return java_vm;
}

jint JavaVMExt::HandleGetEnv(/*out*/void** env, jint version) {
  std::vector<GetEnvHook> env_hooks;
  {
    ReaderMutexLock rmu(Thread::Current(), env_hooks_lock_);
    env_hooks.assign(env_hooks_.begin(), env_hooks_.end());
  }
  for (GetEnvHook hook : env_hooks) {
    jint res = hook(this, env, version);
    if (res == JNI_OK) {
      return JNI_OK;
    } else if (res != JNI_EVERSION) {
      LOG(ERROR) << "Error returned from a plugin GetEnv handler! " << res;
      return res;
    }
  }
  LOG(ERROR) << "Bad JNI version passed to GetEnv: " << version;
  return JNI_EVERSION;
}

// Add a hook to handle getting environments from the GetEnv call.
void JavaVMExt::AddEnvironmentHook(GetEnvHook hook) {
  CHECK(hook != nullptr) << "environment hooks shouldn't be null!";
  WriterMutexLock wmu(Thread::Current(), env_hooks_lock_);
  env_hooks_.push_back(hook);
}

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 " << current_method->PrettyMethod();
  }

  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, ThreadState::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.
  std::string_view class_name = method->GetDeclaringClassDescriptorView();
  if (!trace_.empty() && class_name.find(trace_) != std::string_view::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* const 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;
}

void JavaVMExt::CheckGlobalRefAllocationTracking() {
  if (LIKELY(enable_allocation_tracking_delta_ == 0)) {
    return;
  }
  size_t simple_free_capacity = globals_.FreeCapacity();
  if (UNLIKELY(simple_free_capacity <= enable_allocation_tracking_delta_)) {
    if (!allocation_tracking_enabled_) {
      LOG(WARNING) << "Global reference storage appears close to exhaustion, program termination "
                   << "may be imminent. Enabling allocation tracking to improve abort diagnostics. "
                   << "This will result in program slow-down.";

      old_allocation_tracking_state_ = runtime_->GetHeap()->IsAllocTrackingEnabled();
      if (!old_allocation_tracking_state_) {
        // Need to be guaranteed suspended.
        ScopedObjectAccess soa(Thread::Current());
        ScopedThreadSuspension sts(soa.Self(), ThreadState::kNative);
        gc::AllocRecordObjectMap::SetAllocTrackingEnabled(true);
      }
      allocation_tracking_enabled_ = true;
    }
  } else {
    if (UNLIKELY(allocation_tracking_enabled_)) {
      if (!old_allocation_tracking_state_) {
        // Need to be guaranteed suspended.
        ScopedObjectAccess soa(Thread::Current());
        ScopedThreadSuspension sts(soa.Self(), ThreadState::kNative);
        gc::AllocRecordObjectMap::SetAllocTrackingEnabled(false);
      }
      allocation_tracking_enabled_ = false;
    }
  }
}

void JavaVMExt::MaybeTraceGlobals() {
  if (global_ref_report_counter_++ == kGlobalRefReportInterval) {
    global_ref_report_counter_ = 1;
    ATraceIntegerValue("JNI Global Refs", globals_.NEntriesForGlobal());
  }
}

void JavaVMExt::MaybeTraceWeakGlobals() {
  if (weak_global_ref_report_counter_++ == kGlobalRefReportInterval) {
    weak_global_ref_report_counter_ = 1;
    ATraceIntegerValue("JNI Weak Global Refs", weak_globals_.NEntriesForGlobal());
  }
}

jobject JavaVMExt::AddGlobalRef(Thread* self, ObjPtr<mirror::Object> obj) {
  // Check for null after decoding the object to handle cleared weak globals.
  if (obj == nullptr) {
    return nullptr;
  }
  IndirectRef ref;
  std::string error_msg;
  {
    WriterMutexLock mu(self, *Locks::jni_globals_lock_);
    ref = globals_.Add(obj, &error_msg);
    MaybeTraceGlobals();
  }
  if (UNLIKELY(ref == nullptr)) {
    LOG(FATAL) << error_msg;
    UNREACHABLE();
  }
  CheckGlobalRefAllocationTracking();
  return reinterpret_cast<jobject>(ref);
}

void JavaVMExt::WaitForWeakGlobalsAccess(Thread* self) {
  if (UNLIKELY(!MayAccessWeakGlobals(self))) {
    ATraceBegin("Blocking on WeakGlobal access");
    do {
      // Check and run the empty checkpoint before blocking so the empty checkpoint will work in the
      // presence of threads blocking for weak ref access.
      self->CheckEmptyCheckpointFromWeakRefAccess(Locks::jni_weak_globals_lock_);
      weak_globals_add_condition_.WaitHoldingLocks(self);
    } while (!MayAccessWeakGlobals(self));
    ATraceEnd();
  }
}

jweak JavaVMExt::AddWeakGlobalRef(Thread* self, ObjPtr<mirror::Object> obj) {
  if (obj == nullptr) {
    return nullptr;
  }
  MutexLock mu(self, *Locks::jni_weak_globals_lock_);
  // CMS needs this to block for concurrent reference processing because an object allocated during
  // the GC won't be marked and concurrent reference processing would incorrectly clear the JNI weak
  // ref. But CC (gUseReadBarrier == true) doesn't because of the to-space invariant.
  if (!gUseReadBarrier) {
    WaitForWeakGlobalsAccess(self);
  }
  std::string error_msg;
  IndirectRef ref = weak_globals_.Add(obj, &error_msg);
  MaybeTraceWeakGlobals();
  if (UNLIKELY(ref == nullptr)) {
    LOG(FATAL) << error_msg;
    UNREACHABLE();
  }
  return reinterpret_cast<jweak>(ref);
}

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

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

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, *Locks::jni_globals_lock_);
    os << "; globals=" << globals_.Capacity();
  }
  {
    MutexLock mu(self, *Locks::jni_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(!gUseReadBarrier);
  Thread* const self = Thread::Current();
  MutexLock mu(self, *Locks::jni_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_.store(false, std::memory_order_seq_cst);
}

void JavaVMExt::AllowNewWeakGlobals() {
  CHECK(!gUseReadBarrier);
  Thread* self = Thread::Current();
  MutexLock mu(self, *Locks::jni_weak_globals_lock_);
  allow_accessing_weak_globals_.store(true, std::memory_order_seq_cst);
  weak_globals_add_condition_.Broadcast(self);
}

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

ObjPtr<mirror::Object> JavaVMExt::DecodeGlobal(IndirectRef ref) {
  return globals_.Get(ref);
}

void JavaVMExt::UpdateGlobal(Thread* self, IndirectRef ref, ObjPtr<mirror::Object> result) {
  WriterMutexLock mu(self, *Locks::jni_globals_lock_);
  globals_.Update(ref, result);
}

ObjPtr<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(IndirectReferenceTable::GetIndirectRefKind(ref), kWeakGlobal);
  if (LIKELY(MayAccessWeakGlobals(self))) {
    return weak_globals_.Get(ref);
  }
  MutexLock mu(self, *Locks::jni_weak_globals_lock_);
  return DecodeWeakGlobalLocked(self, ref);
}

ObjPtr<mirror::Object> JavaVMExt::DecodeWeakGlobalLocked(Thread* self, IndirectRef ref) {
  if (kDebugLocking) {
    Locks::jni_weak_globals_lock_->AssertHeld(self);
  }
  // TODO: Handle the already null case without waiting.
  // TODO: Otherwise we should just wait for kInitMarkingDone, and track which weak globals were
  // marked at that point. We would only need one mark bit per entry in the weak_globals_ table,
  // and a quick pass over that early on during reference processing.
  WaitForWeakGlobalsAccess(self);
  return weak_globals_.Get(ref);
}

ObjPtr<mirror::Object> JavaVMExt::DecodeWeakGlobalAsStrong(IndirectRef ref) {
  // The target is known to be alive. Simple `Get()` with read barrier is enough.
  return weak_globals_.Get(ref);
}

ObjPtr<mirror::Object> JavaVMExt::DecodeWeakGlobalDuringShutdown(Thread* self, IndirectRef ref) {
  DCHECK_EQ(IndirectReferenceTable::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 (!gUseReadBarrier) {
    DCHECK(allow_accessing_weak_globals_.load(std::memory_order_seq_cst));
  }
  return weak_globals_.Get(ref);
}

bool JavaVMExt::IsWeakGlobalCleared(Thread* self, IndirectRef ref) {
  DCHECK_EQ(IndirectReferenceTable::GetIndirectRefKind(ref), kWeakGlobal);
  MutexLock mu(self, *Locks::jni_weak_globals_lock_);
  WaitForWeakGlobalsAccess(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, ObjPtr<mirror::Object> result) {
  MutexLock mu(self, *Locks::jni_weak_globals_lock_);
  weak_globals_.Update(ref, result);
}

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

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

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

bool JavaVMExt::LoadNativeLibrary(JNIEnv* env,
                                  const std::string& path,
                                  jobject class_loader,
                                  jclass caller_class,
                                  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;
  std::string caller_location;
  {
    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.
    ObjPtr<mirror::ClassLoader> loader = soa.Decode<mirror::ClassLoader>(class_loader);

    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    if (class_linker->IsBootClassLoader(loader)) {
      loader = nullptr;
      class_loader = nullptr;
    }
    if (caller_class != nullptr) {
      ObjPtr<mirror::Class> caller = soa.Decode<mirror::Class>(caller_class);
      ObjPtr<mirror::DexCache> dex_cache = caller->GetDexCache();
      if (dex_cache != nullptr) {
        caller_location = dex_cache->GetLocation()->ToModifiedUtf8();
      }
    }

    class_loader_allocator = class_linker->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.
      //
      // This isn't very common. So spend some time to get a readable message.
      auto call_to_string = [&](jobject obj) -> std::string {
        if (obj == nullptr) {
          return "null";
        }
        // Handle jweaks. Ignore double local-ref.
        ScopedLocalRef<jobject> local_ref(env, env->NewLocalRef(obj));
        if (local_ref != nullptr) {
          ScopedLocalRef<jclass> local_class(env, env->GetObjectClass(local_ref.get()));
          jmethodID to_string = env->GetMethodID(local_class.get(),
                                                 "toString",
                                                 "()Ljava/lang/String;");
          DCHECK(to_string != nullptr);
          ScopedLocalRef<jobject> local_string(env,
                                               env->CallObjectMethod(local_ref.get(), to_string));
          if (local_string != nullptr) {
            ScopedUtfChars utf(env, reinterpret_cast<jstring>(local_string.get()));
            if (utf.c_str() != nullptr) {
              return utf.c_str();
            }
          }
          if (env->ExceptionCheck()) {
            // We can't do much better logging, really. So leave it with a Describe.
            env->ExceptionDescribe();
            env->ExceptionClear();
          }
          return "(Error calling toString)";
        }
        return "null";
      };
      std::string old_class_loader = call_to_string(library->GetClassLoader());
      std::string new_class_loader = call_to_string(class_loader);
      StringAppendF(error_msg, "Shared library \"%s\" already opened by "
          "ClassLoader %p(%s); can't open in ClassLoader %p(%s)",
          path.c_str(),
          library->GetClassLoader(),
          old_class_loader.c_str(),
          class_loader,
          new_class_loader.c_str());
      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.

  // Retrieve the library path from the classloader, if necessary.
  ScopedLocalRef<jstring> library_path(env, GetLibrarySearchPath(env, class_loader));

  Locks::mutator_lock_->AssertNotHeld(self);
  const char* path_str = path.empty() ? nullptr : path.c_str();
  bool needs_native_bridge = false;
  char* nativeloader_error_msg = nullptr;
  void* handle = android::OpenNativeLibrary(
      env,
      runtime_->GetTargetSdkVersion(),
      path_str,
      class_loader,
      (caller_location.empty() ? nullptr : caller_location.c_str()),
      library_path.get(),
      &needs_native_bridge,
      &nativeloader_error_msg);
  VLOG(jni) << "[Call to dlopen(\"" << path << "\", RTLD_NOW) returned " << handle << "]";

  if (handle == nullptr) {
    *error_msg = nativeloader_error_msg;
    android::NativeLoaderFreeErrorMessage(nativeloader_error_msg);
    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,
                          needs_native_bridge,
                          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 = library->FindSymbol("JNI_OnLoad", nullptr, android::kJNICallTypeRegular);
  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 << "\"]";
    using JNI_OnLoadFn = int(*)(JavaVM*, void*);
    JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
    int version = (*jni_on_load)(this, nullptr);

    if (IsSdkVersionSetAndAtMost(runtime_->GetTargetSdkVersion(), SdkVersion::kL)) {
      // Make sure that sigchain owns SIGSEGV.
      EnsureFrontOfChain(SIGSEGV);
    }

    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 (JavaVMExt::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;
}

static void* FindCodeForNativeMethodInAgents(ArtMethod* m) REQUIRES_SHARED(Locks::mutator_lock_) {
  std::string jni_short_name(m->JniShortName());
  std::string jni_long_name(m->JniLongName());
  for (const std::unique_ptr<ti::Agent>& agent : Runtime::Current()->GetAgents()) {
    void* fn = agent->FindSymbol(jni_short_name);
    if (fn != nullptr) {
      VLOG(jni) << "Found implementation for " << m->PrettyMethod()
                << " (symbol: " << jni_short_name << ") in " << *agent;
      return fn;
    }
    fn = agent->FindSymbol(jni_long_name);
    if (fn != nullptr) {
      VLOG(jni) << "Found implementation for " << m->PrettyMethod()
                << " (symbol: " << jni_long_name << ") in " << *agent;
      return fn;
    }
  }
  return nullptr;
}

void* JavaVMExt::FindCodeForNativeMethod(ArtMethod* m, std::string* error_msg, bool can_suspend) {
  CHECK(m->IsNative());
  ObjPtr<mirror::Class> c = m->GetDeclaringClass();
  // If this is a static method, it could be called before the class has been initialized.
  CHECK(c->IsInitializing() || !m->NeedsClinitCheckBeforeCall())
      << c->GetStatus() << " " << m->PrettyMethod();
  Thread* const self = Thread::Current();
  void* native_method = libraries_->FindNativeMethod(self, m, error_msg, can_suspend);
  if (native_method == nullptr && can_suspend) {
    // Lookup JNI native methods from native TI Agent libraries. See runtime/ti/agent.h for more
    // information. Agent libraries are searched for native methods after all jni libraries.
    native_method = FindCodeForNativeMethodInAgents(m);
  }
  return native_method;
}

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

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

jstring JavaVMExt::GetLibrarySearchPath(JNIEnv* env, jobject class_loader) {
  if (class_loader == nullptr) {
    return nullptr;
  }
  ScopedObjectAccess soa(env);
  ObjPtr<mirror::Object> mirror_class_loader = soa.Decode<mirror::Object>(class_loader);
  if (!mirror_class_loader->InstanceOf(WellKnownClasses::dalvik_system_BaseDexClassLoader.Get())) {
    return nullptr;
  }
  return soa.AddLocalReference<jstring>(
      WellKnownClasses::dalvik_system_BaseDexClassLoader_getLdLibraryPath->InvokeVirtual<'L'>(
          soa.Self(), mirror_class_loader));
}

// JNI Invocation interface.

extern "C" EXPORT jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  ScopedTrace trace(__FUNCTION__);
  const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
  if (JavaVMExt::IsBadJniVersion(args->version)) {
    LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
    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)) {
    return JNI_ERR;
  }

  // When `ART_CRASH_RUNTIME_DELIBERATELY` is defined (which happens only in the
  // case of a test APEX), we crash the runtime here on purpose, to test the
  // behavior of rollbacks following a failed ART Mainline Module update.
#ifdef ART_CRASH_RUNTIME_DELIBERATELY
  LOG(FATAL) << "Runtime crashing deliberately for testing purposes.";
#endif

  // Initialize native loader. This step makes sure we have
  // everything set up before we start using JNI.
  android::InitializeNativeLoader();

  Runtime* runtime = Runtime::Current();
  bool started = runtime->Start();
  if (!started) {
    delete Thread::Current()->GetJniEnv();
    delete runtime->GetJavaVM();
    LOG(WARNING) << "CreateJavaVM failed";
    return JNI_ERR;
  }

  *p_env = Thread::Current()->GetJniEnv();
  *p_vm = runtime->GetJavaVM();
  return JNI_OK;
}

extern "C" EXPORT 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" EXPORT jint JNI_GetDefaultJavaVMInitArgs(void* /*vm_args*/) {
  return JNI_ERR;
}

}  // namespace art
