JNI_CreateJavaVM(Runtime::Create())


service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd
   前面的关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。

/frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
  AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    // Everything up to '--' or first non '-' arg goes to the vm.
    //
    // The first argument after the VM args is the "parent dir", which
    // is currently unused.
    //
    // After the parent dir, we expect one or more the following internal
    // arguments :
    //
    // --zygote : Start in zygote mode
    // --start-system-server : Start the system server.
    // --application : Start in application (stand alone, non zygote) mode.
    // --nice-name : The nice name for this process.
    //
    // For non zygote starts, these arguments will be followed by
    // the main class name. All remaining arguments are passed to
    // the main method of this class.
    //
    // For zygote starts, all remaining arguments are passed to the zygote.
    // main function.
    //
    // Note that we must copy argument string values since we will rewrite the
    // entire argument block when we apply the nice name to argv0.

    int i;
    for (i = 0; i < argc; i++) {
        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }
        runtime.addOption(strdup(argv[i]));
    }

    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag); // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

 

/frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
    /* start the virtual machine */
    JniInvocation jni_invocation;
//load libart.so  初始化JniInvocation::JNI_CreateJavaVM_接口 jni_invocation.Init(NULL); JNIEnv
* env; if (startVm(&mJavaVM, &env) != 0) { return; } onVmCreated(env); /* * Register android functions. */ if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); /* keep going */ } else { env->CallStaticVoidMethod(startClass, startMeth, strArray); } } free(slashClassName); ALOGD("Shutting down VM\n"); if (mJavaVM->DetachCurrentThread() != JNI_OK) ALOGW("Warning: unable to detach main thread\n"); if (mJavaVM->DestroyJavaVM() != 0) ALOGW("Warning: VM did not shut down cleanly\n"); } int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) {
//JavaVM 参数配置 ................
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { ALOGE("JNI_CreateJavaVM failed\n"); goto bail; } }

 JniInvocation是单例类提供了3个接口,但是实际上真正用到的只有一个接口JNI_CreateJavaVM()

class JniInvocation {
 public:
  JniInvocation();

  ~JniInvocation();

  // Initialize JNI invocation API. library should specifiy a valid
  // shared library for opening via dlopen providing a JNI invocation
  // implementation, or null to allow defaulting via
  // persist.sys.dalvik.vm.lib.
  bool Init(const char* library);

  // Exposes which library is actually loaded from the given name. The
  // buffer of size PROPERTY_VALUE_MAX will be used to load the system
  // property for the default library, if necessary. If no buffer is
  // provided, the fallback value will be used.
  static const char* GetLibrary(const char* library, char* buffer);

 private:

  bool FindSymbol(void** pointer, const char* symbol);

  static JniInvocation& GetJniInvocation();

  jint JNI_GetDefaultJavaVMInitArgs(void* vmargs);
  jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
  jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count);

  static JniInvocation* jni_invocation_;

  void* handle_;
  jint (*JNI_GetDefaultJavaVMInitArgs_)(void*);
  jint (*JNI_CreateJavaVM_)(JavaVM**, JNIEnv**, void*);
  jint (*JNI_GetCreatedJavaVMs_)(JavaVM**, jsize, jsize*);

  friend jint JNI_GetDefaultJavaVMInitArgs(void* vm_args);
  friend jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
  friend jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count);
};
        
JniInvocation::JniInvocation() :
    handle_(NULL),
    JNI_GetDefaultJavaVMInitArgs_(NULL),
    JNI_CreateJavaVM_(NULL),
    JNI_GetCreatedJavaVMs_(NULL) {

  LOG_ALWAYS_FATAL_IF(jni_invocation_ != NULL, "JniInvocation instance already initialized");
  jni_invocation_ = this;
}

//加载libart.so
bool JniInvocation::Init(const char* library) { #ifdef HAVE_ANDROID_OS char buffer[PROPERTY_VALUE_MAX]; #else char* buffer = NULL; #endif library = GetLibrary(library, buffer); handle_ = dlopen(library, RTLD_NOW); if (handle_ == NULL) { if (strcmp(library, kLibraryFallback) == 0) { // Nothing else to try. ALOGE("Failed to dlopen %s: %s", library, dlerror()); return false; } // Note that this is enough to get something like the zygote // running, we can't property_set here to fix this for the future // because we are root and not the system user. See // RuntimeInit.commonInit for where we fix up the property to // avoid future fallbacks. http://b/11463182 ALOGW("Falling back from %s to %s after dlopen error: %s", library, kLibraryFallback, dlerror()); library = kLibraryFallback; handle_ = dlopen(library, RTLD_NOW); if (handle_ == NULL) { ALOGE("Failed to dlopen %s: %s", library, dlerror()); return false; } } if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_), "JNI_GetDefaultJavaVMInitArgs")) { return false; }

//给函数指针JNI_CreateJavaVM_赋值
if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_), "JNI_CreateJavaVM")) { return false; } if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_), "JNI_GetCreatedJavaVMs")) { return false; } return true; } jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
//调用动态加载的函数指针
return JNI_CreateJavaVM_(p_vm, p_env, vm_args); } bool JniInvocation::FindSymbol(void** pointer, const char* symbol) { *pointer = dlsym(handle_, symbol); if (*pointer == NULL) { ALOGE("Failed to find symbol %s: %s\n", symbol, dlerror()); dlclose(handle_); handle_ = NULL; return false; } return true; }
// 实现jni.h中的JNI_CreateJavaVM方法
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) { return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args); }

.....................

libart.so中的方法在Jni_internal.cc中实现

FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_), "JNI_CreateJavaVM"

 

//Jni_internal.cc
// JNI Invocation interface.
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
  if (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;
  }
  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" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize, jsize* vm_count) {
  Runtime* runtime = Runtime::Current();
  if (runtime == nullptr) {
    *vm_count = 0;
  } else {
    *vm_count = 1;
    vms[0] = runtime->GetJavaVM();
  }
  return JNI_OK;
}

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

 

 

很明显,除了JNI_CreateJavaVM(),另外两个方法没什么作用

/art/runtime/jni_internal.cc
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
 
// 第一大步:创建Runtime
if (!Runtime::Create(options, ignore_unrecognized)) { return JNI_ERR; } Runtime* runtime = Runtime::Current();
  // 第二大步:Runtime::start() 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; }

   instance_是Runtime类的静态成员变量,它指向进程中的一个Runtime单例。这个Runtime单例描述的就是当前进程的ART虚拟机实例。

class Runtime {
  static Runtime* instance_;

  InstructionSet instruction_set_;
  bool is_zygote_;
  bool must_relocate_;
  bool is_concurrent_gc_enabled_;
  bool is_explicit_gc_disabled_;
  bool dex2oat_enabled_;
  bool image_dex2oat_enabled_;
  std::string boot_class_path_string_;
  std::string class_path_string_;

  gc::Heap* heap_;

  ThreadList* thread_list_;
  InternTable* intern_table_;
  ClassLinker* class_linker_;
  JavaVMExt* java_vm_;
 // A non-zero value indicates that a thread has been created but not yet initialized. Guarded by
  // the shutdown lock so that threads aren't born while we're shutting down.
  size_t threads_being_born_ GUARDED_BY(Locks::runtime_shutdown_lock_);
}

 

/art/runtime/runtime.cc
bool Runtime::Create(const RuntimeOptions& options, bool ignore_unrecognized) {
  // Runtime是单例,只会被初始化一次
  if (Runtime::instance_ != NULL) {
    return false;
  }

//这个log初始化需要一点点时间,这个时候LOG(TAG)是打印不出来的  InitLogging(NULL);
// Calls Locks::Init() as a side effect. instance_ = new Runtime; if (!instance_->Init(options, ignore_unrecognized)) { delete instance_; instance_ = NULL; return false; } return true; } bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) { CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize); MemMap::Init();
//解析Andriod VM的配置参数 std::unique_ptr
<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized)); if (options.get() == nullptr) { LOG(ERROR) << "Failed to parse options"; return false; } VLOG(startup) << "Runtime::Init -verbose:startup enabled"; QuasiAtomic::Startup(); Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_);
// boot_class_path_string_ =
// /system/framework/core-libart.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:
// /system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:
// /system/framework/voip-common.jar:/system/framework/ims-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:
// /system/framework/apache-xml.jar:/system/framework/HtcLegacy.jar:/system/framework/mediatek-common.jar:/system/framework/mediatek-framework.jar:
// /system/framework/mediatek-telephony-common.jar:/system/framework/dolby_ds.jar boot_class_path_string_
= options->boot_class_path_string_; class_path_string_ = options->class_path_string_; properties_ = options->properties_; compiler_callbacks_ = options->compiler_callbacks_; patchoat_executable_ = options->patchoat_executable_; must_relocate_ = options->must_relocate_; is_zygote_ = options->is_zygote_; is_explicit_gc_disabled_ = options->is_explicit_gc_disabled_; dex2oat_enabled_ = options->dex2oat_enabled_; image_dex2oat_enabled_ = options->image_dex2oat_enabled_; vfprintf_ = options->hook_vfprintf_; exit_ = options->hook_exit_; abort_ = options->hook_abort_; default_stack_size_ = options->stack_size_; stack_trace_file_ = options->stack_trace_file_; compiler_executable_ = options->compiler_executable_; compiler_options_ = options->compiler_options_; image_compiler_options_ = options->image_compiler_options_; image_location_ = options->image_; max_spins_before_thin_lock_inflation_ = options->max_spins_before_thin_lock_inflation_; monitor_list_ = new MonitorList; monitor_pool_ = MonitorPool::Create(); thread_list_ = new ThreadList; intern_table_ = new InternTable; verify_ = options->verify_; if (options->interpreter_only_) { GetInstrumentation()->ForceInterpretOnly(); } heap_ = new gc::Heap(options->heap_initial_size_, options->heap_growth_limit_, options->heap_min_free_, options->heap_max_free_, options->heap_target_utilization_, options->foreground_heap_growth_multiplier_, options->heap_maximum_size_, options->heap_non_moving_space_capacity_, options->image_, options->image_isa_, options->collector_type_, options->background_collector_type_, options->parallel_gc_threads_, options->conc_gc_threads_, options->low_memory_mode_, options->long_pause_log_threshold_, options->long_gc_log_threshold_, options->ignore_max_footprint_, options->use_tlab_, options->verify_pre_gc_heap_, options->verify_pre_sweeping_heap_, options->verify_post_gc_heap_, options->verify_pre_gc_rosalloc_, options->verify_pre_sweeping_rosalloc_, options->verify_post_gc_rosalloc_, options->use_homogeneous_space_compaction_for_oom_, options->min_interval_homogeneous_space_compaction_by_oom_);

  BlockSignals();
  InitPlatformSignalHandlers();

  // Always initialize the signal chain so that any calls to sigaction get
  // correctly routed to the next in the chain regardless of whether we
  // have claimed the signal or not.
// 加载如下两个库:
// dlsym(RTLD_NEXT, "sigaction");
// dlsym(RTLD_DEFAULT, "sigprocmask");
  InitializeSignalChain();

  if (implicit_null_checks_ || implicit_so_checks_ || implicit_suspend_checks_) {
    //所有信号都要交给fault_manager来处理,所以这个很早就初始化了
    fault_manager.Init();  

    // These need to be in a specific order.  The null point check handler must be
    // after the suspend check and stack overflow check handlers.
    if (implicit_suspend_checks_) {  //false
      suspend_handler_ = new SuspensionHandler(&fault_manager);
    }

    if (implicit_so_checks_) {    //true
      stack_overflow_handler_ = new StackOverflowHandler(&fault_manager);
    }

    if (implicit_null_checks_) {   //ture
      null_pointer_handler_ = new NullPointerHandler(&fault_manager);
    }

    if (kEnableJavaStackTraceHandler) {  //false
      new JavaStackTraceHandler(&fault_manager);
    }
  }

  java_vm_ = new JavaVMExt(this, options.get());

  Thread::Startup();

  // ClassLinker needs an attached thread, but we can't fully attach a thread without creating
  // objects. We can't supply a thread group yet; it will be fixed later. Since we are the main
  // thread, we do not get a java peer.
  Thread* self = Thread::Attach("main", false, nullptr, false); class_linker_ = new ClassLinker(intern_table_);
if (GetHeap()->HasImageSpace()) { //android虚拟机启动时,这里为真 class_linker_->InitFromImage(); if (kIsDebugBuild) { GetHeap()->GetImageSpace()->VerifyImageAllocations(); } } else {
     .............
  } }

void Runtime::BlockSignals() {
  SignalSet signals;
  signals.Add(SIGPIPE);
  // SIGQUIT is used to dump the runtime's state (including stack traces).
  signals.Add(SIGQUIT);
  // SIGUSR1 is used to initiate a GC.
  signals.Add(SIGUSR1);
#if defined(HAVE_ANDROID_OS) && defined(MTK_DUMMY_PREDUMP)
  signals.Add(SIGSTKFLT);
#endif
  signals.Block();
}

 

//art/runtime/signal_set.h
class SignalSet {
 public:
  SignalSet() {
    if (sigemptyset(&set_) == -1) {
      PLOG(FATAL) << "sigemptyset failed";
    }
  }

  void Add(int signal) {
    if (sigaddset(&set_, signal) == -1) {
      PLOG(FATAL) << "sigaddset " << signal << " failed";
    }
  }

  void Block() {
    if (sigprocmask(SIG_BLOCK, &set_, NULL) == -1) {
      PLOG(FATAL) << "sigprocmask failed";
    }
  }

  int Wait() {
    // Sleep in sigwait() until a signal arrives. gdb causes EINTR failures.
    int signal_number;
    int rc = TEMP_FAILURE_RETRY(sigwait(&set_, &signal_number));
    if (rc != 0) {
      PLOG(FATAL) << "sigwait failed";
    }
    return signal_number;
  }

 private:
  sigset_t set_;
};

 

// art/runtime/runtime_android.cc
void Runtime::InitPlatformSignalHandlers() {
  bool enableHtcSigHandler = false;
#ifdef HAVE_ANDROID_OS
  LOG(ERROR) << "Has define HAVE_ANDROID_OS";
  char prop_value[PROPERTY_VALUE_MAX];
  property_get("persist.dalvik.sighandle.enable", prop_value, IsShippingRom() ? "0" : "1");
  enableHtcSigHandler = (strcmp(prop_value, "0") != 0);
#endif

  if (enableHtcSigHandler) {
#if defined(__LP64__)
    LOG(ERROR) << "Has define __LP64__";
    // Follow bionic/libc/bionic/pthread_create.cpp to install alter stack on LP64 platform
    stack_t ss;
    ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    if (ss.ss_sp != MAP_FAILED) {
      ss.ss_size = SIGSTKSZ;
      ss.ss_flags = 0;
      int ret = sigaltstack(&ss, NULL);
      LOG(INFO) << StringPrintf("do sigaltstack at %s, size: %zd-byte, ret: %d", __FUNCTION__, ss.ss_size, ret);
    } else {
      LOG(INFO) << StringPrintf("do mmap altstack at %s, size: %d-byte, MAP_FAILED", __FUNCTION__, SIGSTKSZ);
    }
#endif

    struct sigaction action;
    memset(&action, 0, sizeof(action));
    sigemptyset(&action.sa_mask);
   action.sa_sigaction = NativeCrashSigHandler;
    // Use the three-argument sa_sigaction handler.
    action.sa_flags |= SA_SIGINFO;
    // Use the alternate signal stack so we can catch stack overflows.
    action.sa_flags |= SA_ONSTACK;

    // initialize for backup native crash handler
    memset(&gOldActionSIGABRT, 0, sizeof(gOldActionSIGABRT));
    memset(&gOldActionSIGSEGV, 0, sizeof(gOldActionSIGSEGV));

    // Register the native crash signal.
    int rc = 0;
    rc += sigaction(SIGABRT, &action, &gOldActionSIGABRT);
    rc += sigaction(SIGSEGV, &action, &gOldActionSIGSEGV);
    CHECK_EQ(rc, 0);
  }
}

 

// art/runtime/fault_handler.h
class
FaultManager { public: FaultManager(); ~FaultManager(); void Init(); void Shutdown(); void EnsureArtActionInFrontOfSignalChain(); void HandleFault(int sig, siginfo_t* info, void* context);    //接受signal时,首先调用这个函数 void HandleNestedSignal(int sig, siginfo_t* info, void* context); void AddHandler(FaultHandler* handler, bool generated_code);  //添加多个FaultHandler来处理消息 void RemoveHandler(FaultHandler* handler); // Note that the following two functions are called in the context of a signal handler. // The IsInGeneratedCode() function checks that the mutator lock is held before it // calls GetMethodAndReturnPCAndSP(). // TODO: think about adding lock assertions and fake lock and unlock functions. void GetMethodAndReturnPcAndSp(siginfo_t* siginfo, void* context, mirror::ArtMethod** out_method, uintptr_t* out_return_pc, uintptr_t* out_sp) NO_THREAD_SAFETY_ANALYSIS; bool IsInGeneratedCode(siginfo_t* siginfo, void *context, bool check_dex_pc) NO_THREAD_SAFETY_ANALYSIS; private: std::vector<FaultHandler*> generated_code_handlers_; std::vector<FaultHandler*> other_handlers_; struct sigaction oldaction_; bool initialized_; DISALLOW_COPY_AND_ASSIGN(FaultManager); }; class FaultHandler { public: explicit FaultHandler(FaultManager* manager); virtual ~FaultHandler() {} FaultManager* GetFaultManager() { return manager_; } virtual bool Action(int sig, siginfo_t* siginfo, void* context) = 0; protected: FaultManager* const manager_; private: DISALLOW_COPY_AND_ASSIGN(FaultHandler); };

class NullPointerHandler FINAL : public FaultHandler {
 public:
  explicit NullPointerHandler(FaultManager* manager);

  bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE;

 private:
  DISALLOW_COPY_AND_ASSIGN(NullPointerHandler);
};

class StackOverflowHandler FINAL : public FaultHandler {
 public:
  explicit StackOverflowHandler(FaultManager* manager);

  bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE;

 private:
  DISALLOW_COPY_AND_ASSIGN(StackOverflowHandler);
};

 

// art/runtime/fault_handler.cc
// fault_manager是全局变量,虚拟机里面仅此一份
FaultManager fault_manager;

FaultManager::FaultManager() : initialized_(false) {
  sigaction(SIGSEGV, nullptr, &oldaction_);
}

static void art_fault_handler(int sig, siginfo_t* info, void* context) {
  fault_manager.HandleFault(sig, info, context);
}

void FaultManager::AddHandler(FaultHandler* handler, bool generated_code) {
  if (generated_code) {
    generated_code_handlers_.push_back(handler);
  } else {
    other_handlers_.push_back(handler);
  }
}

void FaultManager::Init() {
  CHECK(!initialized_);
  struct sigaction action;
  SetUpArtAction(&action);

  // Set our signal handler now.
  int e = sigaction(SIGSEGV, &action, &oldaction_);
  if (e != 0) {
    VLOG(signals) << "Failed to claim SEGV: " << strerror(errno);
  }
  // Make sure our signal handler is called before any user handlers.
  ClaimSignalChain(SIGSEGV, &oldaction_);
  initialized_ = true;
}

static void SetUpArtAction(struct sigaction* action) {
  action->sa_sigaction = art_fault_handler;  //signal就是通过这个函数处理
  sigemptyset(&action->sa_mask);
  action->sa_flags = SA_SIGINFO | SA_ONSTACK;
#if !defined(__APPLE__) && !defined(__mips__)
  action->sa_restorer = nullptr;
#endif
}

void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
  // BE CAREFUL ALLOCATING HERE INCLUDING USING LOG(...)
  //
  // If malloc calls abort, it will be holding its lock.
  // If the handler tries to call malloc, it will deadlock.
  VLOG(signals) << "Handling fault";
  if (IsInGeneratedCode(info, context, true)) {
    VLOG(signals) << "in generated code, looking for handler";
    for (const auto& handler : generated_code_handlers_) {
      VLOG(signals) << "invoking Action on handler " << handler;
      if (handler->Action(sig, info, context)) {
#ifdef TEST_NESTED_SIGNAL
        // In test mode we want to fall through to stack trace handler
        // on every signal (in reality this will cause a crash on the first
        // signal).
        break;
#else
        // We have handled a signal so it's time to return from the
        // signal handler to the appropriate place.
        return;
#endif
      }
    }
  }

  // We hit a signal we didn't handle.  This might be something for which
  // we can give more information about so call all registered handlers to see
  // if it is.
  for (const auto& handler : other_handlers_) {
    if (handler->Action(sig, info, context)) {
      return;
    }
  }

  // Set a breakpoint in this function to catch unhandled signals.
  art_sigsegv_fault(); //这个就只打了一行log

//如果系统能处理(也就是我们注册的FaultHandler能处理)则不会调用
InvokeUserSignalHandler()
  //先系统处理,系统处理不了才给用户处理
// Pass this on to the next handler in the chain, or the default if none. InvokeUserSignalHandler(sig, info, context); } NullPointerHandler::NullPointerHandler(FaultManager* manager) : FaultHandler(manager) { manager_->AddHandler(this, true); } StackOverflowHandler::StackOverflowHandler(FaultManager* manager) : FaultHandler(manager) { manager_->AddHandler(this, true); }

 

 

// art/sigchainlib/sigchain.cc
extern "C" void InvokeUserSignalHandler(int sig, siginfo_t* info, void* context) {
  // Check the arguments.
  CheckSignalValid(sig);

  // The signal must have been claimed in order to get here.  Check it.
  if (!user_sigactions[sig].IsClaimed()) {
    printf("InvokeUserSignalHandler() call abort()");
    abort();
  }

  const struct sigaction& action = user_sigactions[sig].GetAction();
  if ((action.sa_flags & SA_SIGINFO) == 0) {
    if (action.sa_handler != NULL) {
      action.sa_handler(sig);
    } else {
       // M: google seems add dummy libsigchain to avoid external module calling sigchain
       //     and change sigchain.cc to link as static library, but we think sigchain.cc only can work
       //     as shared library, so workaround to call bionic c sigaction() manually.
       //signal(sig, SIG_DFL);
       struct sigaction sa;
       sigemptyset(&sa.sa_mask);
       sa.sa_handler = SIG_DFL;
       sa.sa_flags = action.sa_flags;
       SigActionFnPtr linked_sigaction = reinterpret_cast<SigActionFnPtr>(linked_sigaction_sym);
       linked_sigaction(sig, &sa, nullptr);
       
       raise(sig);
    }
  } else {
    if (action.sa_sigaction != NULL) {
      action.sa_sigaction(sig, info, context);
    } else {
       // M: google seems add dummy libsigchain to avoid external module calling sigchain
       //     and change sigchain.cc to link as static library, but we think sigchain.cc only can work
       //     as shared library, so workaround to call bionic c sigaction() manually.
       //signal(sig, SIG_DFL);
       struct sigaction sa;
       sigemptyset(&sa.sa_mask);
       sa.sa_handler = SIG_DFL;
       sa.sa_flags = action.sa_flags;
       SigActionFnPtr linked_sigaction = reinterpret_cast<SigActionFnPtr>(linked_sigaction_sym);
       linked_sigaction(sig, &sa, nullptr);
       
       raise(sig);
    }
  }
}

 

 

// User's signal handlers  
//全局变量 定义每种非可靠信号的用户处理方式
// _NSIG = 32
static SignalAction user_sigactions[_NSIG]; class SignalAction { public: SignalAction() : claimed_(false) { } // Claim the signal and keep the action specified. void Claim(const struct sigaction& action) { action_ = action; claimed_ = true; } // Unclaim the signal and restore the old action. void Unclaim(int signal) { claimed_ = false; sigaction(signal, &action_, NULL); // Restore old action. } // Get the action associated with this signal. const struct sigaction& GetAction() const { return action_; } // Is the signal claimed? bool IsClaimed() const { return claimed_; } // Change the recorded action to that specified. void SetAction(const struct sigaction& action) { action_ = action; } private: struct sigaction action_; // Action to be performed. bool claimed_; // Whether signal is claimed or not. };

 

 

// art/runtime/thread.cc
void Thread::Startup() { CHECK(!is_started_); is_started_ = true; { MutexLock mu(nullptr, *Locks::thread_suspend_count_lock_); resume_cond_ = new ConditionVariable("Thread resumption condition variable", *Locks::thread_suspend_count_lock_); } // Allocate a TLS slot.  CHECK_PTHREAD_CALL(pthread_key_create, (&Thread::pthread_key_self_, Thread::ThreadExitCallback), "self key"); // Double-check the TLS slot allocation. if (pthread_getspecific(pthread_key_self_) != nullptr) { LOG(FATAL) << "Newly-created pthread TLS slot is not nullptr"; } } 

        创建好ART虚拟机堆后,Runtime类的成员函数Init接着又创建了一个JavaVMExt实例。这个JavaVMExt实例最终是要返回给 调用者的,使得调用者可以通过该JavaVMExt实例来和ART虚拟机交互。再接下来,Runtime类的成员函数Init通过Thread类的成员函 数Attach将当前线程作为ART虚拟机的主线程,使得当前线程可以调用ART虚拟机提供的JNI接口。      

        Runtime类的成员函数GetHeap返回的便是当前ART虚拟机的堆,也就是前面创建的ART虚拟机堆。通过调用Heap类的成员函数 GetContinuousSpaces可以获得堆里面的连续空间列表。如果这个列表的第一个连续空间是一个Image空间,那么就调用 ClassLinker类的静态成员函数CreateFromImage来创建一个ClassLinker对象。

       后面我们分析ART虚拟机的垃圾收集机制时会看到,ART虚拟机的堆包含有三个连续空间和一个不连续空间。三个连续空间分别用来分配不同的对象。当第一个连续空间不是Image空间时,就表明当前进程不是Zygote进程,而是安装应用程序时启动的一个dex2oat进程。安装应用程序时启动的 dex2oat进程也会在内部创建一个ART虚拟机,不过这个ART虚拟机是用来将DEX字节码编译成本地机器指令的,而Zygote进程创建的ART虚 拟机是用来运行应用程序的。

 

frameworks/base/core/jni/AndroidRuntime.cpp
class AndroidRuntime {
    /*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;

    /** return a pointer to the VM running in this process */
    static JavaVM* getJavaVM() { return mJavaVM; }

    /** return a pointer to the JNIEnv pointer for this thread */

/*static*/ JNIEnv* AndroidRuntime::getJNIEnv()
{
    JNIEnv* env;
    JavaVM* vm = AndroidRuntime::getJavaVM();
    assert(vm != NULL);

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
        return NULL;
    return env;
} } // art
/runtime/thread.cc
//创建TLS变量,即线程本地存储变量
void Thread::Startup() { CHECK(!is_started_); is_started_ = true; { MutexLock mu(nullptr, *Locks::thread_suspend_count_lock_); resume_cond_ = new ConditionVariable("Thread resumption condition variable", *Locks::thread_suspend_count_lock_); } // Allocate a TLS slot. CHECK_PTHREAD_CALL(pthread_key_create, (&Thread::pthread_key_self_, Thread::ThreadExitCallback), "self key"); // Double-check the TLS slot allocation. if (pthread_getspecific(pthread_key_self_) != nullptr) { LOG(FATAL) << "Newly-created pthread TLS slot is not nullptr"; } } inline Thread* Thread::Current() { // We rely on Thread::Current returning NULL for a detached thread, so it's not obvious // that we can replace this with a direct %fs access on x86. if (!is_started_) { return NULL; } else { void* thread = pthread_getspecific(Thread::pthread_key_self_); return reinterpret_cast<Thread*>(thread); } } // JNI methods JNIEnvExt* GetJniEnv() const { return tlsPtr_.jni_env; } struct JNIEnvExt : public JNIEnv { JNIEnvExt(Thread* self, JavaVMExt* vm); ~JNIEnvExt(); Thread* const self; JavaVMExt* vm; } void Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm) { // This function does all the initialization that must be run by the native thread it applies to. // (When we create a new thread from managed code, we allocate the Thread* in Thread::Create so // we can handshake with the corresponding native thread when it's ready.) Check this native // thread hasn't been through here already... CHECK(Thread::Current() == nullptr); SetUpAlternateSignalStack(); InitCpu(); InitTlsEntryPoints(); RemoveSuspendTrigger(); InitCardTable(); InitTid(); // Set pthread_self_ ahead of pthread_setspecific, that makes Thread::Current function, this // avoids pthread_self_ ever being invalid when discovered from Thread::Current(). tlsPtr_.pthread_self = pthread_self(); CHECK(is_started_); CHECK_PTHREAD_CALL(pthread_setspecific, (Thread::pthread_key_self_, this), "attach self"); DCHECK_EQ(Thread::Current(), this); tls32_.thin_lock_thread_id = thread_list->AllocThreadId(this); InitStackHwm(); tlsPtr_.jni_env = new JNIEnvExt(this, java_vm); thread_list->Register(this); } Thread* Thread::Attach(const char* thread_name, bool as_daemon, jobject thread_group, bool create_peer) { Thread* self; Runtime* runtime = Runtime::Current(); if (runtime == nullptr) { LOG(ERROR) << "Thread attaching to non-existent runtime: " << thread_name; return nullptr; } { MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_); if (runtime->IsShuttingDownLocked()) { LOG(ERROR) << "Thread attaching while runtime is shutting down: " << thread_name; return nullptr; } else { Runtime::Current()->StartThreadBirth(); self = new Thread(as_daemon); self->Init(runtime->GetThreadList(), runtime->GetJavaVM()); Runtime::Current()->EndThreadBirth(); } } CHECK_NE(self->GetState(), kRunnable); self->SetState(kNative); // If we're the main thread, ClassLinker won't be created until after we're attached, // so that thread needs a two-stage attach. Regular threads don't need this hack. // In the compiler, all threads need this hack, because no-one's going to be getting // a native peer! if (create_peer) { self->CreatePeer(thread_name, as_daemon, thread_group); } else { // These aren't necessary, but they improve diagnostics for unit tests & command-line tools. if (thread_name != nullptr) { self->tlsPtr_.name->assign(thread_name); ::art::SetThreadName(thread_name); } else if (self->GetJniEnv()->check_jni) { LOG(WARNING) << *Thread::Current() << " attached without supplying a name"; } } return self; }

 

 

art/runtime/gc/heap.cc
Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max_free,
       ....................
          lgrind()),
      use_tlab_(use_tlab),
      main_space_backup_(nullptr),
      min_interval_homogeneous_space_compaction_by_oom_(
          min_interval_homogeneous_space_compaction_by_oom),
      last_time_homogeneous_space_compaction_by_oom_(NanoTime()),
      use_homogeneous_space_compaction_for_oom_(use_homogeneous_space_compaction_for_oom) {

  ChangeCollector(desired_collector_type_);
  live_bitmap_.reset(new accounting::HeapBitmap(this));
  mark_bitmap_.reset(new accounting::HeapBitmap(this));
  // Requested begin for the alloc space, to follow the mapped image and oat files
  byte* requested_alloc_space_begin = nullptr;
  if (!image_file_name.empty()) {
    std::string error_msg;
    space::ImageSpace* image_space = space::ImageSpace::Create(image_file_name.c_str(),
                                                               image_instruction_set,
                                                               &error_msg);
    if (image_space != nullptr) {
      AddSpace(image_space); // Oat files referenced by image files immediately follow them in memory, ensure alloc space
      // isn't going to get in the middle
      byte* oat_file_end_addr = image_space->GetImageHeader().GetOatFileEnd();
      CHECK_GT(oat_file_end_addr, image_space->End());
      requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize);
    } else {
      LOG(WARNING) << "Could not create image space with image file '" << image_file_name << "'. "
                   << "Attempting to fall back to imageless running. Error was: " << error_msg;
    }
  }
}

 参数original_image_file_name描述的就是前面提到的Image文件的路径。如果它的值不等于空的话,那么就以它为参数,调用 ImageSpace类的静态成员函数Create创建一个Image空间,并且调用Heap类的成员函数AddContinuousSpace将该 Image空间作为本进程的ART虚拟机堆的第一个连续空间。

art/runtime/gc/space/image_space.cc
/*我们假设参数original_image_file_name的值等于“/system/framework/boot.art”,那么ImageSpace类的静态成员函数Create的执行逻辑实际上就是:
        1. 检查文件/system/framework/boot.art是否存在。如果存在,那么就以它为参数,创建一个Image空间。否则的话,执行下一步。
        2. 检查文件/data/dalvik-cache/system@framework@boot.art@classes.dex是否存在。如果存在,那么就以它为参数,创建一个Image空间。否则的话,执行下一步。
        3. 调用ImageSpace类的静态成员函数GenerateImage在/data/dalvik-cache目录下生成一个 system@framework@boot.art@classes.dex,然后再以该文件为参数,创建一个Image空间。
*/ ImageSpace
* ImageSpace::Create(const char* image_location, const InstructionSet image_isa, std::string* error_msg) { const bool found_image = FindImageFilename(image_location, image_isa, &system_filename, &has_system, &cache_filename, &dalvik_cache_exists, &has_cache, &is_global_cache); ImageSpace* space; bool relocate = Runtime::Current()->ShouldRelocate(); bool can_compile = Runtime::Current()->IsImageDex2OatEnabled(); if (!can_compile) { *error_msg = "Not attempting to compile image because -Xnoimage-dex2oat"; return nullptr; } else if (!dalvik_cache_exists) { *error_msg = StringPrintf("No place to put generated image."); return nullptr; } else if (!ImageCreationAllowed(is_global_cache, error_msg)) { return nullptr; } else if (!GenerateImage(cache_filename, image_isa, error_msg)) { *error_msg = StringPrintf("Failed to generate image '%s': %s", cache_filename.c_str(), error_msg->c_str()); // We failed to create files, remove any possibly garbage output. // Since ImageCreationAllowed was true above, we are the zygote // and therefore the only process expected to generate these for // the device. PruneDexCache(image_isa); return nullptr; } else { // Note that we must not use the file descriptor associated with // ScopedFlock::GetFile to Init the image file. We want the file // descriptor (and the associated exclusive lock) to be released when // we leave Create. ScopedFlock image_lock; image_lock.Init(cache_filename.c_str(), error_msg); space = ImageSpace::Init(cache_filename.c_str(), image_location, true, error_msg); if (space == nullptr) { *error_msg = StringPrintf("Failed to load generated image '%s': %s", cache_filename.c_str(), error_msg->c_str()); } return space; } } static bool GenerateImage(const std::string& image_file_name) { const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString()); std::vector<std::string> boot_class_path; Split(boot_class_path_string, ':', boot_class_path); ...... std::vector<std::string> arg_vector; std::string dex2oat(GetAndroidRoot()); dex2oat += (kIsDebugBuild ? "/bin/dex2oatd" : "/bin/dex2oat"); arg_vector.push_back(dex2oat); std::string image_option_string("--image="); image_option_string += image_file_name; arg_vector.push_back(image_option_string); ...... for (size_t i = 0; i < boot_class_path.size(); i++) { arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]); } std::string oat_file_option_string("--oat-file="); oat_file_option_string += image_file_name; oat_file_option_string.erase(oat_file_option_string.size() - 3); oat_file_option_string += "oat"; arg_vector.push_back(oat_file_option_string); ......
  return Exec(arg_vector, error_msg);
}

#echo $BOOTCLASSPATH
/system/framework/core-libart.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/ims-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/apache-xml.jar:/system/framework/HtcLegacy.jar:/system/framework/mediatek-common.jar:/system/framework/mediatek-framework.jar:/system/framework/mediatek-telephony-common.jar:/system/framework/dolby_ds.jar

-----------------------------

ImageSpace类的静态成员函数GenerateImage实际上就调用dex2oat工具在/data/dalvik-cache目录下生成 两个文件:system@framework@boot.art@classes.dex和 system@framework@boot.art@classes.oat。

       system@framework@boot.art@classes.dex是一个Image文件,通过--image选项传递给dex2oat工具, 里面包含了一些需要在Zygote进程启动时预加载的类。这些需要预加载的类由/system/framework/framework.jar文件里面 的preloaded-classes文件指定。

       system@framework@boot.art@classes.oat是一个OAT文件,通过--oat-file选项传递给dex2oat工 具,它是由系统启动路径中指定的jar文件生成的。每一个jar文件都通过一个--dex-file选项传递给dex2oat工具。这样dex2oat工 具就可以将它们所包含的classes.dex文件里面的DEX字节码翻译成本地机器指令。

       这样,我们就得到了一个包含有多个DEX文件的OAT文件system@framework@boot.art@classes.oat。

       通过上面的分析,我们就清楚地看到了ART运行时所需要的OAT文件是如何产生的了。其中,由系统启动类路径指定的DEX文件生成的OAT文件称为类型为 BOOT的OAT文件,即boot.art文件。有了这个背景知识之后,接下来我们就继续分析ART运行时是如何加载OAT文件的。

art/runtime/utils.cc
bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) {
  const std::string command_line(Join(arg_vector, ' '));

  CHECK_GE(arg_vector.size(), 1U) << command_line;

  // Convert the args to char pointers.
  const char* program = arg_vector[0].c_str();
  std::vector<char*> args;
  for (size_t i = 0; i < arg_vector.size(); ++i) {
    const std::string& arg = arg_vector[i];
    char* arg_str = const_cast<char*>(arg.c_str());
    CHECK(arg_str != nullptr) << i;
    args.push_back(arg_str);
  }
  args.push_back(NULL);

  // fork and exec
  pid_t pid = fork();
  if (pid == 0) {
    // no allocation allowed between fork and exec

    // change process groups, so we don't get reaped by ProcessManager
    setpgid(0, 0);

  execv(program, &args[0]);

    PLOG(ERROR) << "Failed to execv(" << command_line << ")";
    exit(1);
  } else {
    if (pid == -1) {
      *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
                                command_line.c_str(), strerror(errno));
      return false;
    }

    // wait for subprocess to finish
    int status;
    pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
    if (got_pid != pid) {
      *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
                                "wanted %d, got %d: %s",
                                command_line.c_str(), pid, got_pid, strerror(errno));
      return false;
    }
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
      *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
                                command_line.c_str());
      return false;
    }
  }
return true; }

       ART运行时提供了一个OatFile类,通过调用它的静态成员函数Open可以在本进程中加载OAT文件,它的实现如下所示:

/art/runtime/oat_file.cc
OatFile* OatFile::Open(const std::string& filename,
                       const std::string& location,
                       byte* requested_base,
                       bool executable,
                       std::string* error_msg) {
  CHECK(!filename.empty()) << location;
  CheckLocation(filename);
  std::unique_ptr<OatFile> ret;
  if (kUsePortableCompiler && executable) {
    // If we are using PORTABLE, use dlopen to deal with relocations.
    //
    // We use our own ELF loader for Quick to deal with legacy apps that
    // open a generated dex file by name, remove the file, then open
    // another generated dex file with the same name. 
    ret.reset(OpenDlopen(filename, location, requested_base, error_msg));
  } else {
    // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
    //
    // On target, dlopen may fail when compiling due to selinux restrictions on installd.
    //
    // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.
    // This won't work for portable runtime execution because it doesn't process relocations.
    std::unique_ptr<File> file(OS::OpenFileForReading(filename.c_str()));
    if (file.get() == NULL) {
      *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
      return nullptr;
    }
    ret.reset(OpenElfFile(file.get(), location, requested_base, false, executable, error_msg));

    // It would be nice to unlink here. But we might have opened the file created by the
    // ScopedLock, which we better not delete to avoid races. TODO: Investigate how to fix the API
    // to allow removal when we know the ELF must be borked.
  }
  return ret.release();
}



OatFile* OatFile::OpenDlopen(const std::string& elf_filename,
                             const std::string& location,
                             byte* requested_base,
                             std::string* error_msg) {
  std::unique_ptr<OatFile> oat_file(new OatFile(location, true));
  bool success = oat_file->Dlopen(elf_filename, requested_base, error_msg);
  if (!success) {
    return nullptr;
  }
  return oat_file.release();
}

bool OatFile::Dlopen(const std::string& elf_filename, byte* requested_base,
                     std::string* error_msg) {
  char* absolute_path = realpath(elf_filename.c_str(), NULL);
  if (absolute_path == NULL) {
    *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
    return false;
  }
  dlopen_handle_ = dlopen(absolute_path, RTLD_NOW);
  free(absolute_path);
  if (dlopen_handle_ == NULL) {
    *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
    return false;
  }
  begin_ = reinterpret_cast<byte*>(dlsym(dlopen_handle_, "oatdata"));
  if (begin_ == NULL) {
    *error_msg = StringPrintf("Failed to find oatdata symbol in '%s': %s", elf_filename.c_str(),
                              dlerror());
    return false;
  }
  if (requested_base != NULL && begin_ != requested_base) {
    *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
                              "oatdata=%p != expected=%p /proc/self/maps:\n",
                              begin_, requested_base);
    ReadFileToString("/proc/self/maps", error_msg);
    return false;
  }
  end_ = reinterpret_cast<byte*>(dlsym(dlopen_handle_, "oatlastword"));
  if (end_ == NULL) {
    *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s': %s", elf_filename.c_str(),
                              dlerror());
    return false;
  }
  // Readjust to be non-inclusive upper bound.
  end_ += sizeof(uint32_t);
  return Setup(error_msg);
}

OatFile* OatFile::OpenElfFile(File* file,
                              const std::string& location,
                              byte* requested_base,
                              bool writable,
                              bool executable,
                              std::string* error_msg) {
  std::unique_ptr<OatFile> oat_file(new OatFile(location, executable));
  bool success = oat_file->ElfFileOpen(file, requested_base, writable, executable, error_msg);
  if (!success) {
    CHECK(!error_msg->empty());
    return nullptr;
  }
  return oat_file.release();
}

...................................

 

class Runtime {
  static Runtime* instance_;

  InstructionSet instruction_set_;
  bool is_zygote_;
  bool must_relocate_;
  bool is_concurrent_gc_enabled_;
  bool is_explicit_gc_disabled_;
  bool dex2oat_enabled_;
  bool image_dex2oat_enabled_;
  std::string boot_class_path_string_;
  std::string class_path_string_;

  gc::Heap* heap_;

  ThreadList* thread_list_;

  InternTable* intern_table_;

  ClassLinker* class_linker_;

  JavaVMExt* java_vm_;
}

 

//zygote64 进程的初始化
01
-04 15:39:58.140 394 394 E art : Runtime::Init() 01-04 15:39:58.148 394 394 E art : new gc::Heap() 01-04 15:39:58.151 394 394 E art : space::ImageSpace::Create() 01-04 15:39:58.151 394 394 E art : ImageSpace::Create()... 01-04 15:39:58.178 394 394 E art : ............... 01-04 15:39:58.178 394 394 E art : GenerateImage() ..... 01-04 15:39:58.199 394 394 E art : GenerateImage: /system/bin/dex2oat --image=/data/dalvik-cache/arm64/system@framework@boot.art --dex-file=/system/framework/core-libart.jar --dex-file=/system/framework/conscrypt.jar --dex-file=/system/framework/okhttp.jar --dex-file=/system/framework/core-junit.jar --dex-file=/system/framework/bouncycastle.jar --dex-file=/system/framework/ext.jar --dex-file=/system/framework/framework.jar --dex-file=/system/framework/telephony-common.jar --dex-file=/system/framework/voip-common.jar --dex-file=/system/framework/ims-common.jar --dex-file=/system/framework/mms-common.jar --dex-file=/system/framework/android.policy.jar --dex-file=/system/framework/apache-xml.jar --dex-file=/system/framework/HtcLegacy.jar --dex-file=/system/framework/mediatek-common.jar --dex-file=/system/framework/mediatek-framework.jar --dex-file=/system/framework/mediatek-telephony-common.jar --dex-file=/system/framework/dolby_ds.jar --oat-file=/data/dalvik-cache/arm64/system@framework@boot.oat --instruction-set=arm64 --instruction-set-feature ...............................//dex2oat编译image文件 01-04 15:41:31.783 394 394 E art : image_space != nullptr 01-04 15:41:31.871 394 394 E art : BlockSignals() and InitPlatformSignalHandlers() 01-04 15:41:31.871 394 394 E art : boot_class_path_string_:/system/framework/core-libart.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/ims-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/apache-xml.jar:/system/framework/HtcLegacy.jar:/system/framework/mediatek-common.jar:/system/framework/mediatek-framework.jar:/system/framework/mediatek-telephony-common.jar:/system/framework/dolby_ds.jar 01-04 15:41:31.871 394 394 E art : class_path_string_: 01-04 15:41:31.871 394 394 E art : image_location_:/system/framework/boot.art 01-04 15:41:31.871 394 394 E art : signals.Add(SIGSTKFLT); 01-04 15:41:31.871 394 394 E art : Runtime::InitPlatformSignalHandlers() 01-04 15:41:31.871 394 394 E art : Has define HAVE_ANDROID_OS 01-04 15:41:31.871 394 394 I art : buildType: userdebug, roAaReport: , roSf: 0 01-04 15:41:31.871 394 394 E art : enableHtcSigHandler == true 01-04 15:41:31.871 394 394 E art : Has define __LP64__ 01-04 15:41:31.871 394 394 I art : do sigaltstack at InitPlatformSignalHandlers, size: 12288-byte, ret: 0 01-04 15:41:31.871 394 394 E art : Runtime::InitPlatformSignalHandlers() action.sa_sigaction = NativeCrashSigHandler 01-04 15:41:31.871 394 394 E art : InitializeSignalChain() 01-04 15:41:31.871 394 394 E art : fault_manager.Init() 01-04 15:41:31.871 394 394 E art : SetUpArtAction() action->sa_sigaction = art_fault_handler; 01-04 15:41:31.871 394 394 E art : new StackOverflowHandler 01-04 15:41:31.871 394 394 E art : new NullPointerHandler 01-04 15:41:31.881 394 394 E art : HTC+++ is_zygote_ = true 01-04 15:41:31.881 394 394 E art : GetHeap()->HasImageSpace() 01-04 15:41:31.886 394 394 E art : after initImageSpace 01-04 15:41:31.893 394 394 I art : Runtime::Start Zygote: isShippingRom=0

 

//dex2oat参数:
GenerateImage: 
/system/bin/dex2oat 
--image=/data/dalvik-cache/arm64/system@framework@boot.art 
--dex-file=/system/framework/core-libart.jar 
--dex-file=/system/framework/conscrypt.jar 
--dex-file=/system/framework/okhttp.jar 
--dex-file=/system/framework/core-junit.jar 
--dex-file=/system/framework/bouncycastle.jar 
--dex-file=/system/framework/ext.jar 
--dex-file=/system/framework/framework.jar 
--dex-file=/system/framework/telephony-common.jar 
--dex-file=/system/framework/voip-common.jar 
--dex-file=/system/framework/ims-common.jar 
--dex-file=/system/framework/mms-common.jar 
--dex-file=/system/framework/android.policy.jar 
--dex-file=/system/framework/apache-xml.jar 
--dex-file=/system/framework/HtcLegacy.jar 
--dex-file=/system/framework/mediatek-common.jar 
--dex-file=/system/framework/mediatek-framework.jar 
--dex-file=/system/framework/mediatek-telephony-common.jar 
--dex-file=/system/framework/dolby_ds.jar 
--oat-file=/data/dalvik-cache/arm64/system@framework@boot.oat 
--instruction-set=arm64 --instruction-set-feature

 

frameworks/base/cmds/app_process/app_main.cpp
void main() {
   //解析虚拟机相关的参数
   AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

/frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    //注册虚拟机创建的相关jni函数,主要是为了JNI_CreateJavaVM函数的调用 
    JniInvocation jni_invocation;
    //Init函数会加载libart.so库,使用dlopen()给函数指针JNI_CreateJavaVM找到对应的接口
    jni_invocation.Init(NULL);

    //创建虚拟机
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }

    //注册相关的jni函数
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        //找到com.android.internal.os.ZygoteInit.java类的main()函数method id 然后去执行
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
    }
}


int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
    }

    return 0;
}


java_vm_ext.cc
// JNI Invocation interface.
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
  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;
  //创建Runtime
  if (!Runtime::Create(options, ignore_unrecognized)) {
    ATRACE_END();
    return JNI_ERR;
  }
  Runtime* runtime = Runtime::Current();
  //调用runtime->Start();
  bool started = runtime->Start();

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

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM