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