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.cppint main(int argc, char* constargv[])

{

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.

inti;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

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;

}

}

Vectorargs;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"));

}charprop[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.cppvoid AndroidRuntime::start(const char* className, const Vector&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");gotobail;

}

}

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

classJniInvocation {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.sobool JniInvocation::Init(const char*library) {

#ifdef HAVE_ANDROID_OScharbuffer[PROPERTY_VALUE_MAX];#else

char* buffer =NULL;#endiflibrary=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(&JNI_GetDefaultJavaVMInitArgs_),"JNI_GetDefaultJavaVMInitArgs")) {return false;

}

//给函数指针JNI_CreateJavaVM_赋值if (!FindSymbol(reinterpret_cast(&JNI_CreateJavaVM_),"JNI_CreateJavaVM")) {return false;

}if (!FindSymbol(reinterpret_cast(&JNI_GetCreatedJavaVMs_),"JNI_GetCreatedJavaVMs")) {return false;

}return true;

}

jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void*vm_args) {

//调用动态加载的函数指针returnJNI_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) {returnJniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);

}

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

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

FindSymbol(reinterpret_cast(&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(vm_args);if (IsBadJniVersion(args->version)) {

LOG(ERROR)<< "Bad JNI version passed to CreateJavaVM:" << args->version;returnJNI_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)) {returnJNI_ERR;

}

Runtime* runtime =Runtime::Current();bool started = runtime->Start();if (!started) {

delete Thread::Current()->GetJniEnv();

delete runtime->GetJavaVM();

LOG(WARNING)<< "CreateJavaVM failed";returnJNI_ERR;

}*p_env = Thread::Current()->GetJniEnv();*p_vm = runtime->GetJavaVM();returnJNI_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();

}returnJNI_OK;

}//Historically unsupported.

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

// 第一大步:创建Runtimeif (!Runtime::Create(options, ignore_unrecognized)) {returnJNI_ERR;

}

Runtime* runtime =Runtime::Current();

// 第二大步:Runtime::start()

bool started= runtime->Start();

if (!started) {

delete Thread::Current()->GetJniEnv();

delete runtime->GetJavaVM();

LOG(WARNING)<< "CreateJavaVM failed";returnJNI_ERR;

}*p_env = Thread::Current()->GetJniEnv();

*p_vm = runtime->GetJavaVM();returnJNI_OK;

}

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

classRuntime {static Runtime*instance_;

InstructionSet instruction_set_;boolis_zygote_;boolmust_relocate_;boolis_concurrent_gc_enabled_;boolis_explicit_gc_disabled_;booldex2oat_enabled_;boolimage_dex2oat_enabled_;

std::stringboot_class_path_string_;

std::stringclass_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_ = newRuntime;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_ptroptions(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_= newMonitorList;

monitor_pool_=MonitorPool::Create();

thread_list_= newThreadList;

intern_table_= newInternTable;

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

classSignalSet {public:

SignalSet() {if (sigemptyset(&set_) == -1) {

PLOG(FATAL)<< "sigemptyset failed";

}

}void Add(intsignal) {if (sigaddset(&set_, signal) == -1) {

PLOG(FATAL)<< "sigaddset" << signal << "failed";

}

}voidBlock() {if (sigprocmask(SIG_BLOCK, &set_, NULL) == -1) {

PLOG(FATAL)<< "sigprocmask failed";

}

}intWait() {//Sleep in sigwait() until a signal arrives. gdb causes EINTR failures.

intsignal_number;int rc = TEMP_FAILURE_RETRY(sigwait(&set_, &signal_number));if (rc != 0) {

PLOG(FATAL)<< "sigwait failed";

}returnsignal_number;

}private:

sigset_t set_;

};

//art/runtime/runtime_android.cc

voidRuntime::InitPlatformSignalHandlers() {bool enableHtcSigHandler = false;

#ifdef HAVE_ANDROID_OS

LOG(ERROR)<< "Has define HAVE_ANDROID_OS";charprop_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

structsigaction 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

classFaultManager {public:

FaultManager();~FaultManager();voidInit();voidShutdown();voidEnsureArtActionInFrontOfSignalChain();void HandleFault(int sig, siginfo_t* info, void*context);    //接受signal时,首先调用这个函数void HandleNestedSignal(int sig, siginfo_t* info, void*context);void AddHandler(FaultHandler* handler, boolgenerated_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, boolcheck_dex_pc)

NO_THREAD_SAFETY_ANALYSIS;private:

std::vectorgenerated_code_handlers_;

std::vectorother_handlers_;structsigaction oldaction_;boolinitialized_;

DISALLOW_COPY_AND_ASSIGN(FaultManager);

};class FaultHandler {public:explicit FaultHandler(FaultManager*manager);virtual ~FaultHandler() {}

FaultManager*GetFaultManager() {returnmanager_;

}virtual bool Action(int sig, siginfo_t* siginfo, void* context) = 0;protected:

FaultManager* constmanager_;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, boolgenerated_code) {if(generated_code) {

generated_code_handlers_.push_back(handler);

}else{

other_handlers_.push_back(handler);

}

}voidFaultManager::Init() {

CHECK(!initialized_);structsigaction action;

SetUpArtAction(&action);//Set our signal handler now.

int e = sigaction(SIGSEGV, &action, &oldaction_);if (e != 0) {

VLOG(signals)<< "Failed to claim SEGV:" <

}//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" <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);

structsigaction sa;

sigemptyset(&sa.sa_mask);

sa.sa_handler=SIG_DFL;

sa.sa_flags=action.sa_flags;

SigActionFnPtr linked_sigaction= reinterpret_cast(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);

structsigaction sa;

sigemptyset(&sa.sa_mask);

sa.sa_handler=SIG_DFL;

sa.sa_flags=action.sa_flags;

SigActionFnPtr linked_sigaction= reinterpret_cast(linked_sigaction_sym);

linked_sigaction(sig,&sa, nullptr);

raise(sig);

}

}

}

//User's signal handlers//全局变量 定义每种非可靠信号的用户处理方式

// _NSIG = 32

static SignalAction user_sigactions[_NSIG];classSignalAction {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(intsignal) {

claimed_= false;

sigaction(signal,&action_, NULL); //Restore old action.

}//Get the action associated with this signal.

const struct sigaction& GetAction() const{returnaction_;

}//Is the signal claimed?

bool IsClaimed() const{returnclaimed_;

}//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

voidThread::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.cppclassAndroidRuntime {/*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变量,即线程本地存储变量voidThread::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_) {returnNULL;

}else{void* thread = pthread_getspecific(Thread::pthread_key_self_);return reinterpret_cast(thread);

}

}//JNI methods

JNIEnvExt* GetJniEnv() const{returntlsPtr_.jni_env;

}struct JNIEnvExt : publicJNIEnv {

JNIEnvExt(Thread* self, JavaVMExt*vm);~JNIEnvExt();

Thread* constself;

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, boolas_daemon, jobject thread_group,boolcreate_peer) {

Thread*self;

Runtime* runtime =Runtime::Current();if (runtime ==nullptr) {

LOG(ERROR)<< "Thread attaching to non-existent runtime:" <

}

{

MutexLock mu(nullptr,*Locks::runtime_shutdown_lock_);if (runtime->IsShuttingDownLocked()) {

LOG(ERROR)<< "Thread attaching while runtime is shutting down:" <

}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";

}

}returnself;

}

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: " <

}

}

}

参数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,constInstructionSet 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";returnnullptr;

}else if (!dalvik_cache_exists) {*error_msg = StringPrintf("No place to put generated image.");returnnullptr;

}else if (!ImageCreationAllowed(is_global_cache, error_msg)) {returnnullptr;

}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);returnnullptr;

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

}returnspace;

}

}static bool GenerateImage(const std::string&image_file_name) {const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString());

std::vector<:string>boot_class_path;

Split(boot_class_path_string,':', boot_class_path);

......

std::vector<: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<:string>& arg_vector, std::string*error_msg) {const std::string command_line(Join(arg_vector, ' '));

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

const char* program = arg_vector[0].c_str();

std::vectorargs;for (size_t i = 0; i < arg_vector.size(); ++i) {const std::string& arg =arg_vector[i];char* arg_str = const_cast(arg.c_str());

CHECK(arg_str!= nullptr) <

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

intstatus;

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()) <

CheckLocation(filename);

std::unique_ptrret;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_ptrfile(OS::OpenFileForReading(filename.c_str()));if (file.get() ==NULL) {*error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));returnnullptr;

}

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.

}returnret.release();

}

OatFile* OatFile::OpenDlopen(const std::string&elf_filename,const std::string&location,byte*requested_base,

std::string*error_msg) {

std::unique_ptr oat_file(new OatFile(location, true));

bool success= oat_file->Dlopen(elf_filename, requested_base, error_msg);if (!success) {returnnullptr;

}returnoat_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(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(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);returnSetup(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 oat_file(newOatFile(location, executable));

bool success= oat_file->ElfFileOpen(file, requested_base, writable, executable, error_msg);if (!success) {

CHECK(!error_msg->empty());returnnullptr;

}returnoat_file.release();

}

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

classRuntime {static Runtime*instance_;

InstructionSet instruction_set_;boolis_zygote_;boolmust_relocate_;boolis_concurrent_gc_enabled_;boolis_explicit_gc_disabled_;booldex2oat_enabled_;boolimage_dex2oat_enabled_;

std::stringboot_class_path_string_;

std::stringclass_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 394E art : Runtime::Init()01-04 15:39:58.148 394 394 E art : newgc::Heap()01-04 15:39:58.151 394 394E art : space::ImageSpace::Create()01-04 15:39:58.151 394 394E art : ImageSpace::Create()...01-04 15:39:58.178 394 394E art : ...............01-04 15:39:58.178 394 394E 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 !=nullptr01-04 15:41:31.871 394 394E 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.jar01-04 15:41:31.871 394 394E art : class_path_string_:01-04 15:41:31.871 394 394 E art : image_location_:/system/framework/boot.art01-04 15:41:31.871 394 394E art : signals.Add(SIGSTKFLT);01-04 15:41:31.871 394 394E art : Runtime::InitPlatformSignalHandlers()01-04 15:41:31.871 394 394E art : Has define HAVE_ANDROID_OS01-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 394E 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 =NativeCrashSigHandler01-04 15:41:31.871 394 394E art : InitializeSignalChain()01-04 15:41:31.871 394 394E 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 : newStackOverflowHandler01-04 15:41:31.871 394 394 E art : newNullPointerHandler01-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 394E art : after initImageSpace01-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.cppvoidmain() {//解析虚拟机相关的参数

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.cppvoid AndroidRuntime::start(const char* className, const Vector& options, boolzygote)

{//注册虚拟机创建的相关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, boolzygote)

{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(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();returnJNI_ERR;

}

Runtime* runtime =Runtime::Current();//调用runtime->Start();

bool started = runtime->Start();*p_env = Thread::Current()->GetJniEnv();*p_vm = runtime->GetJavaVM();returnJNI_OK;

}

java的create vm_JNI_CreateJavaVM(Runtime::Create())相关推荐

  1. IDEA 启动报错:java.lang.IllegalStateException: failed to create a child event loop 问题解决

    遇到的问题 昨天电脑自动更新了,今天死活启动不了项目,看到idea的提示是: idea日志如下 根据提示说 查看idea的启动日志: 2018-11-20 17:35:42,010 [ 46737] ...

  2. java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

    java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() ...

  3. Android --- java.lang.RuntimeException: Can‘t create handler inside thread that has not called Loop

    报错信息如下: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.pr ...

  4. MQ java.lang.OutOfMemoryError: unable to create new native thread

    文章目录 1. 问题现象 2. 分析定位 3. 解决方案 4. 结果验证 5. 总结 1. 问题现象 java.lang.OutOfMemoryError: unable to create new ...

  5. JAVA.SQL.SQLNONTRANSIENTCONNECTIONEXCEPTION: COULD NOT CREATE CONNECTION TO DATABASE SERVER. ATTEMPT

    错误信息 java.sql.SQLNonTransientConnectionException: Could not create connection to database server. At ...

  6. 解决java.lang.OutOfMemoryError: unable to create new native thread问题

    解决java.lang.OutOfMemoryError: unable to create new native thread问题 参考文章: (1)解决java.lang.OutOfMemoryE ...

  7. 容器启动失败 ERROR: for log Cannot start service log: OCI runtime create failed: container_linux.go:346

    完整错误信息: ERROR: for log Cannot start service log: OCI runtime create failed: container_linux.go:346: ...

  8. Kubernetes Kubelete 报错 ctr: failed to create shim task: OCI runtime create failed

    最近在工作中加入Kubernetes新的服务器节点的之后,发现 Kubelet 报错如下: ctr: failed to create shim task: OCI runtime create fa ...

  9. Jetson设备下使用docker报错的排错过程完整记录,failed to create shim: OCI runtime create failed: container_linux.go:38

    起因是要使用nvidia部署好的ngc镜像部署 nvidia@nvidia-desktop:~$ sudo docker images REPOSITORY TAG IMAGE ID CREATED ...

  10. OCI runtime create failed: runc create failed: unable to start container process: --docker加载镜像

    OCI runtime create failed: runc create failed: unable to start container process: exec: "env&qu ...

最新文章

  1. Microsoft HoloLens 入华一周年,都有哪些进展?
  2. iOS 真机调试包集合 包含 iOS 12.4 不断更新
  3. VS2010-MFC(常用控件:静态文本框)
  4. lisp eval apply_SICP远古魔法-LISP概览(1-2)
  5. 【剑指offer】面试题04:二维数组中的查找(java)
  6. cocos2d-x之物理引擎初试
  7. linux 上自动执行caffe,linux下caffe的命令运行脚本
  8. ASP.NET简化编辑界面 V2
  9. Python-求解两个字符串的最长公共子序列
  10. Python统计txt文件中的英文单词个数
  11. charles Mock测试总结
  12. 房间混响时间的计算与测量
  13. 阿里云 maven 镜像地址
  14. dota2收集服务器延迟,dota2亚服延迟高的解决办法!
  15. 浅谈C++中的LPVOID类型
  16. 【LeetCode - 247】中心对称数 II
  17. Debian 10 安装fonts-noto-cjk
  18. 如何连接Access数据库
  19. openssl 从内存直接加载CA证书
  20. 从GIS地图生成生成建筑模型

热门文章

  1. substance Pt 工业基础配色及金属配色ID材质
  2. 计算机鼠标能用键盘不能用,电脑键盘鼠标都不能用了,怎么回事?
  3. ps钢笔工具的一些快捷键操作(小白请进)
  4. 用python刷网页浏览量_用python脚本24小时刷浏览器的访问量方法
  5. 职场领导想逼你走时,他会用哪些奇招逼你走?
  6. python打开rar_使用Python解压zip、rar文件
  7. 七周成为数据分析师—Excel实战篇
  8. openStreetMap数据分析举例-使用Qt统计城市科技指数排名
  9. 中兴新支点操作系统——背景、徽标大起底
  10. 三年探索:一条自控、电信/科类学生的技术成长路线