2023年11月29日发(作者:)

JNI_CreateJavaVMRuntime::Create())

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

socket zygote stream 666

onrestart write /sys/android_power/request_state wake

onrestart write /sys/power/state on

onrestart restart media

onrestart restart netd

前⾯的关键字service告诉init进程创建⼀个名为"zygote"的进程,这个zygote进程要执⾏的程序是/system/bin/app_process,后⾯是要传给app_process的参数。

/frameworks/base/cmds/app_process/app_

int main(int argc, char* const argv[])

{

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

// Process command line arguments

// ignore argv[0]

argc--;

argv++;

// Everything up to '--' or first non '-' arg goes to the vm.

//

// The first argument after the VM args is the "parent dir", which

// is currently unused.

//

// After the parent dir, we expect one or more the following internal

// arguments :

//

// --zygote : Start in zygote mode

// --start-system-server : Start the system server.

// --application : Start in application (stand alone, non zygote) mode.

// --nice-name : The nice name for this process.

//

// For non zygote starts, these arguments will be followed by

// the main class name. All remaining arguments are passed to

// the main method of this class.

//

// For zygote starts, all remaining arguments are passed to the zygote.

// main function.

//

// Note that we must copy argument string values since we will rewrite the

// entire argument block when we apply the nice name to argv0.

int i;

for (i = 0; i < argc; i++) {

if (argv[i][0] != '-') {

break;

}

if (argv[i][1] == '-' && argv[i][2] == 0) {

++i; // Skip --.

break;

}

ion(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.

set_process_name(());

}

if (zygote) {

("Init", args);

} else if (className) {

("eInit", 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/

void AndroidRuntime::start(const char* className, const Vector& options)

{

/* start the virtual machine */

JniInvocation jni_invocation;

//load 初始化JniInvocation::JNI_CreateJavaVM_接⼝

jni_(NULL);

JNIEnv* env;

if (startVm(&mJavaVM, &env) != 0) {

return;

}

onVmCreated(env);

/*

* Register android functions.

*/

if (startReg(env) < 0) {

ALOGE("Unable to register all android nativesn");

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

if (mJavaVM->DetachCurrentThread() != JNI_OK)

ALOGW("Warning: unable to detach main threadn");

if (mJavaVM->DestroyJavaVM() != 0)

ALOGW("Warning: VM did not shut down cleanlyn");

}

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)

{

//JavaVM 参数配置

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

if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {

ALOGE("JNI_CreateJavaVM failedn");

goto bail;

}

}

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

jni_invocation_ = this;

}

//加载

bool JniInvocation::Init(const char* library) {

#ifdef HAVE_ANDROID_OS

char buffer[PROPERTY_VALUE_MAX];

#else

char* buffer = NULL;

#endif

library = GetLibrary(library, buffer);

handle_ = dlopen(library, RTLD_NOW);

if (handle_ == NULL) {

if (strcmp(library, kLibraryFallback) == 0) {

// Nothing else to try.

ALOGE("Failed to dlopen %s: %s", library, dlerror());

return false;

}

// Note that this is enough to get something like the zygote

// running, we can't property_set here to fix this for the future

// because we are root and not the system user. See

// Init for where we fix up the property to

// avoid future fallbacks. b/11463182

ALOGW("Falling back from %s to %s after dlopen error: %s",

library, kLibraryFallback, dlerror());

library = kLibraryFallback;

handle_ = dlopen(library, RTLD_NOW);

if (handle_ == NULL) {

ALOGE("Failed to dlopen %s: %s", library, dlerror());

return false;

}

}

if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),

"JNI_GetDefaultJavaVMInitArgs")) {

return false;

}

//给函数指针JNI_CreateJavaVM_赋值

if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),

"JNI_CreateJavaVM")) {

return false;

}

if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),

"JNI_GetCreatedJavaVMs")) {

return false;

}

return true;

}

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

//调⽤动态加载的函数指针

return JNI_CreateJavaVM_(p_vm, p_env, vm_args);

}

bool JniInvocation::FindSymbol(void** pointer, const char* symbol) {

*pointer = dlsym(handle_, symbol);

if (*pointer == NULL) {

ALOGE("Failed to find symbol %s: %sn", symbol, dlerror());

dlclose(handle_);

handle_ = NULL;

return false;

}

return true;

}

// 实现jni.h中的JNI_CreateJavaVM⽅法

extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {

return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);

}

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

中的⽅法在Jni_中实现

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

//Jni_

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

return JNI_EVERSION;

}

RuntimeOptions options;

for (int i = 0; i < args->nOptions; ++i) {

JavaVMOption* option = &args->options[i];

_back(std::make_pair(std::string(option->optionString), option->extraInfo));

// Historically unsupported.

extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* /*vm_args*/) {

return JNI_ERR;

}

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

/art/runtime/jni_

extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {

const JavaVMInitArgs* args = static_cast(vm_args);

// 第⼀⼤步:创建Runtime

if (!Runtime::Create(options, ignore_unrecognized)) {

return JNI_ERR;

}

Runtime* runtime = Runtime::Current();

// 第⼆⼤步:Runtime::start()

bool started = runtime->Start();

if (!started) {

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

delete runtime->GetJavaVM();

LOG(WARNING) << "CreateJavaVM failed";

return JNI_ERR;

}

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

*p_vm = runtime->GetJavaVM();

return JNI_OK;

}

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

class Runtime {

static Runtime* instance_;

InstructionSet instruction_set_;

bool is_zygote_;

bool must_relocate_;

bool is_concurrent_gc_enabled_;

bool is_explicit_gc_disabled_;

bool dex2oat_enabled_;

bool image_dex2oat_enabled_;

std::string boot_class_path_string_;

std::string class_path_string_;

gc::Heap* heap_;

ThreadList* thread_list_;

InternTable* intern_table_;

ClassLinker* class_linker_;

JavaVMExt* java_vm_;

// A non-zero value indicates that a thread has been created but not yet initialized. Guarded by

// the shutdown lock so that threads aren't born while we're shutting down.

size_t threads_being_born_ GUARDED_BY(Locks::runtime_shutdown_lock_);

}

/art/runtime/

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.

compiler_executable_ = options->compiler_executable_;

compiler_options_ = options->compiler_options_;

image_compiler_options_ = options->image_compiler_options_;

image_location_ = options->image_;

max_spins_before_thin_lock_inflation_ = options->max_spins_before_thin_lock_inflation_;

monitor_list_ = new MonitorList;

monitor_pool_ = MonitorPool::Create();

thread_list_ = new ThreadList;

intern_table_ = new InternTable;

verify_ = options->verify_;

if (options->interpreter_only_) {

GetInstrumentation()->ForceInterpretOnly();

}

heap_ = new gc::Heap(options->heap_initial_size_,

options->heap_growth_limit_,

options->heap_min_free_,

options->heap_max_free_,

options->heap_target_utilization_,

options->foreground_heap_growth_multiplier_,

options->heap_maximum_size_,

options->heap_non_moving_space_capacity_,

options->image_,

options->image_isa_,

options->collector_type_,

options->background_collector_type_,

options->parallel_gc_threads_,

options->conc_gc_threads_,

options->low_memory_mode_,

options->long_pause_log_threshold_,

options->long_gc_log_threshold_,

}

void Add(int signal) {

if (sigaddset(&set_, signal) == -1) {

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

}

}

void Block() {

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

PLOG(FATAL) << "sigprocmask failed";

}

}

int Wait() {

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

int signal_number;

int rc = TEMP_FAILURE_RETRY(sigwait(&set_, &signal_number));

if (rc != 0) {

PLOG(FATAL) << "sigwait failed";

}

return signal_number;

}

private:

sigset_t set_;

};

// art/runtime/runtime_

void Runtime::InitPlatformSignalHandlers() {

bool enableHtcSigHandler = false;

#ifdef HAVE_ANDROID_OS

LOG(ERROR) << "Has define HAVE_ANDROID_OS";

char prop_value[PROPERTY_VALUE_MAX];

property_get("", 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_ to install alter stack on LP64 platform

stack_t ss;

_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

if (_sp != MAP_FAILED) {

_size = SIGSTKSZ;

_flags = 0;

int ret = sigaltstack(&ss, NULL);

LOG(INFO) << StringPrintf("do sigaltstack at %s, size: %zd-byte, ret: %d", __FUNCTION__, _size, ret);

} else {

LOG(INFO) << StringPrintf("do mmap altstack at %s, size: %d-byte, MAP_FAILED", __FUNCTION__, SIGSTKSZ);

}

#endif

struct sigaction action;

memset(&action, 0, sizeof(action));

sigemptyset(&_mask);

_sigaction = NativeCrashSigHandler;

// Use the three-argument sa_sigaction handler.

_flags |= SA_SIGINFO;

// Use the alternate signal stack so we can catch stack overflows.

_flags |= SA_ONSTACK;

// initialize for backup native crash handler

memset(&gOldActionSIGABRT, 0, sizeof(gOldActionSIGABRT));

memset(&gOldActionSIGSEGV, 0, sizeof(gOldActionSIGSEGV));

// Register the native crash signal.

int rc = 0;

rc += sigaction(SIGABRT, &action, &gOldActionSIGABRT);

rc += sigaction(SIGSEGV, &action, &gOldActionSIGSEGV);

CHECK_EQ(rc, 0);

}

}

// art/runtime/fault_handler.h

class FaultManager {

public:

FaultManager();

~FaultManager();

void Init();

void Shutdown();

void EnsureArtActionInFrontOfSignalChain();

void HandleFault(int sig, siginfo_t* info, void* context); //接受signal时,⾸先调⽤这个函数

void HandleNestedSignal(int sig, siginfo_t* info, void* context);

void AddHandler(FaultHandler* handler, bool generated_code); //添加多个FaultHandler来处理消息

void RemoveHandler(FaultHandler* handler);

// Note that the following two functions are called in the context of a signal handler.

// The IsInGeneratedCode() function checks that the mutator lock is held before it

// calls GetMethodAndReturnPCAndSP().

// TODO: think about adding lock assertions and fake lock and unlock functions.

void GetMethodAndReturnPcAndSp(siginfo_t* siginfo, void* context, mirror::ArtMethod** out_method,

uintptr_t* out_return_pc, uintptr_t* out_sp)

NO_THREAD_SAFETY_ANALYSIS;

bool IsInGeneratedCode(siginfo_t* siginfo, void *context, bool check_dex_pc)

NO_THREAD_SAFETY_ANALYSIS;

private:

std::vector generated_code_handlers_;

std::vector other_handlers_;

struct sigaction oldaction_;

bool initialized_;

DISALLOW_COPY_AND_ASSIGN(FaultManager);

};

class FaultHandler {

public:

explicit FaultHandler(FaultManager* manager);

protected:

FaultManager* const manager_;

private:

DISALLOW_COPY_AND_ASSIGN(FaultHandler);

};

class NullPointerHandler FINAL : public FaultHandler {

public:

explicit NullPointerHandler(FaultManager* manager);

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

private:

DISALLOW_COPY_AND_ASSIGN(NullPointerHandler);

};

class StackOverflowHandler FINAL : public FaultHandler {

public:

explicit StackOverflowHandler(FaultManager* manager);

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

private:

DISALLOW_COPY_AND_ASSIGN(StackOverflowHandler);

};

// art/runtime/fault_

// 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_Fault(sig, info, context);

}

void FaultManager::AddHandler(FaultHandler* handler, bool generated_code) {

if (generated_code) {

generated_code_handlers_.push_back(handler);

} else {

other_handlers_.push_back(handler);

}

}

void FaultManager::Init() {

CHECK(!initialized_);

struct sigaction action;

SetUpArtAction(&action);

// Set our signal handler now.

int e = sigaction(SIGSEGV, &action, &oldaction_);

if (e != 0) {

VLOG(signals) << "Failed to claim SEGV: " << strerror(errno);

}

// Make sure our signal handler is called before any user handlers.

ClaimSignalChain(SIGSEGV, &oldaction_);

initialized_ = true;

}

static void SetUpArtAction(struct sigaction* action) {

action->sa_sigaction = art_fault_handler; //signal就是通过这个函数处理

sigemptyset(&action->sa_mask);

action->sa_flags = SA_SIGINFO | SA_ONSTACK;

#if !defined(__APPLE__) && !defined(__mips__)

action->sa_restorer = nullptr;

#endif

}

void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {

// BE CAREFUL ALLOCATING HERE INCLUDING USING LOG(...)

//

// If malloc calls abort, it will be holding its lock.

// If the handler tries to call malloc, it will deadlock.

VLOG(signals) << "Handling fault";

if (IsInGeneratedCode(info, context, true)) {

// art/sigchainlib/

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 ((_flags & SA_SIGINFO) == 0) {

if (_handler != NULL) {

_handler(sig);

} else {

// M: google seems add dummy libsigchain to avoid external module calling sigchain

// and change to link as static library, but we think only can work

// as shared library, so workaround to call bionic c sigaction() manually.

//signal(sig, SIG_DFL);

struct sigaction sa;

sigemptyset(&_mask);

_handler = SIG_DFL;

_flags = _flags;

SigActionFnPtr linked_sigaction = reinterpret_cast(linked_sigaction_sym);

linked_sigaction(sig, &sa, nullptr);

raise(sig);

}

} else {

if (_sigaction != NULL) {

_sigaction(sig, info, context);

} else {

// M: google seems add dummy libsigchain to avoid external module calling sigchain

// and change to link as static library, but we think only can work

// as shared library, so workaround to call bionic c sigaction() manually.

//signal(sig, SIG_DFL);

struct sigaction sa;

sigemptyset(&_mask);

_handler = SIG_DFL;

_flags = _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];

class SignalAction {

public:

SignalAction() : claimed_(false) {

}

// Claim the signal and keep the action specified.

void Claim(const struct sigaction& action) {

创建好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/

class AndroidRuntime {

/*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;

/** return a pointer to the VM running in this process */

static JavaVM* getJavaVM() { return mJavaVM; }

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

/*static*/ JNIEnv* AndroidRuntime::getJNIEnv()

{

JNIEnv* env;

JavaVM* vm = AndroidRuntime::getJavaVM();

assert(vm != NULL);

if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)

return NULL;

return env;

}

}

// art/runtime/

//创建TLS变量,即线程本地存储变量

void Thread::Startup() {

CHECK(!is_started_);

is_started_ = true;

{

MutexLock mu(nullptr, *Locks::thread_suspend_count_lock_);

resume_cond_ = new ConditionVariable("Thread resumption condition variable",

*Locks::thread_suspend_count_lock_);

}

// Allocate a TLS slot.

CHECK_PTHREAD_CALL(pthread_key_create, (&Thread::pthread_key_self_, Thread::ThreadExitCallback), "self key");

// Double-check the TLS slot allocation.

if (pthread_getspecific(pthread_key_self_) != nullptr) {

LOG(FATAL) << "Newly-created pthread TLS slot is not nullptr";

}

}

inline Thread* Thread::Current() {

// We rely on Thread::Current returning NULL for a detached thread, so it's not obvious

// that we can replace this with a direct %fs access on x86.

if (!is_started_) {

return NULL;

} else {

void* thread = pthread_getspecific(Thread::pthread_key_self_);

return reinterpret_cast(thread);

}

}

// JNI methods

JNIEnvExt* GetJniEnv() const {

return tlsPtr_.jni_env;

}

struct JNIEnvExt : public JNIEnv {

JNIEnvExt(Thread* self, JavaVMExt* vm);

~JNIEnvExt();

Thread* const self;

JavaVMExt* vm;

}

void Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm) {

// This function does all the initialization that must be run by the native thread it applies to.

// (When we create a new thread from managed code, we allocate the Thread* in Thread::Create so

// we can handshake with the corresponding native thread when it's ready.) Check this native

// thread hasn't been through

CHECK(Thread::Current() == nullptr);

SetUpAlternateSignalStack();

InitCpu();

InitTlsEntryPoints();

RemoveSuspendTrigger();

InitCardTable();

InitTid();

// Set pthread_self_ ahead of pthread_setspecific, that makes Thread::Current function, this

// avoids pthread_self_ ever being invalid when discovered from Thread::Current().

tlsPtr_.pthread_self = pthread_self();

CHECK(is_started_);

CHECK_PTHREAD_CALL(pthread_setspecific, (Thread::pthread_key_self_, this), "attach self");

DCHECK_EQ(Thread::Current(), this);

tls32_.thin_lock_thread_id = thread_list->AllocThreadId(this);

InitStackHwm();

tlsPtr_.jni_env = new JNIEnvExt(this, java_vm);

thread_list->Register(this);

}

Thread* Thread::Attach(const char* thread_name, bool as_daemon, jobject thread_group,

bool create_peer) {

Thread* self;

Runtime* runtime = Runtime::Current();

if (runtime == nullptr) {

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

return nullptr;

}

{

MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);

if (runtime->IsShuttingDownLocked()) {

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

return nullptr;

} else {

Runtime::Current()->StartThreadBirth();

self = new Thread(as_daemon);

self->Init(runtime->GetThreadList(), runtime->GetJavaVM());

Runtime::Current()->EndThreadBirth();

}

}

CHECK_NE(self->GetState(), kRunnable);

self->SetState(kNative);

// If we're the main thread, ClassLinker won't be created until after we're attached,

// so that thread needs a two-stage attach. Regular threads don't need this hack.

// In the compiler, all threads need this hack, because no-one's going to be getting

// a native peer!

if (create_peer) {

self->CreatePeer(thread_name, as_daemon, thread_group);

} else {

// These aren't necessary, but they improve diagnostics for unit tests & command-line tools.

if (thread_name != nullptr) {

self->tlsPtr_.name->assign(thread_name);

::art::SetThreadName(thread_name);

} else if (self->GetJniEnv()->check_jni) {

LOG(WARNING) << *Thread::Current() << " attached without supplying a name";

}

}

return self;

}

art/runtime/gc/

Heap::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_()) {

std::string error_msg;

space::ImageSpace* image_space = space::ImageSpace::Create(image_file_name.c_str(),

image_instruction_set,

&error_msg);

if (image_space != nullptr) {

AddSpace(image_space);

// Oat files referenced by image files immediately follow them in memory, ensure alloc space

// isn't going to get in the middle

byte* oat_file_end_addr = image_space->GetImageHeader().GetOatFileEnd();

CHECK_GT(oat_file_end_addr, image_space->End());

requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize);

} else {

LOG(WARNING) << "Could not create image space with image file '" << image_file_name << "'. "

<< "Attempting to fall back to imageless running. Error was: " << error_msg;

}

}

}

参数original_image_file_name描述的就是前⾯提到的Image⽂件的路径。如果它的值不等于空的话,那么就以它为参数,调⽤ ImageSpace类的静态成员函数Create创建⼀个

Image空间,并且调⽤Heap类的成员函数AddContinuousSpace将该 Image空间作为本进程的ART虚拟机堆的第⼀个连续空间。

art/runtime/gc/space/image_

/*我们假设参数original_image_file_name的值等于“/system/framework/”,那么ImageSpace类的静态成员函数Create的执⾏逻辑实际上就是:

1. 检查⽂件/system/framework/是否存在。如果存在,那么就以它为参数,创建⼀个Image空间。否则的话,执⾏下⼀步。

2. 检查⽂件/data/dalvik-cache/system@framework@@是否存在。如果存在,那么就以它为参数,创建⼀个Image空间。否则的话,执⾏下⼀步。

3. 调⽤ImageSpace类的静态成员函数GenerateImage/data/dalvik-cache⽬录下⽣成⼀个 system@framework@@,然后再以该⽂件为参数,创建⼀个Image空间。

*/

ImageSpace* ImageSpace::Create(const char* image_location,

const InstructionSet image_isa,

std::string* error_msg) {

const bool found_image = FindImageFilename(image_location, image_isa, &system_filename,

&has_system, &cache_filename, &dalvik_cache_exists,

&has_cache, &is_global_cache);

ImageSpace* space;

bool relocate = Runtime::Current()->ShouldRelocate();

bool can_compile = Runtime::Current()->IsImageDex2OatEnabled();

if (!can_compile) {

*error_msg = "Not attempting to compile image because -Xnoimage-dex2oat";

return nullptr;

} else if (!dalvik_cache_exists) {

*error_msg = StringPrintf("No place to put generated image.");

return nullptr;

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

std::vector boot_class_path;

Split(boot_class_path_string, ':', boot_class_path);

......

std::vector arg_vector;

std::string dex2oat(GetAndroidRoot());

dex2oat += (kIsDebugBuild ? "/bin/dex2oatd" : "/bin/dex2oat");

arg__back(dex2oat);

std::string image_option_string("--image=");

image_option_string += image_file_name;

arg__back(image_option_string);

......

for (size_t i = 0; i < boot_class_(); i++) {

arg__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_(oat_file_option_() - 3);

oat_file_option_string += "oat";

arg__back(oat_file_option_string);

......

return Exec(arg_vector, error_msg);

}

#echo $BOOTCLASSPATH

/system/framework/:/system/framework/:/system/framework/:/system/framework/core-

:/system/framework/:/system/framework/:/system/framework/:/system/framework/:/system/framework/voip-

:/system/framework/:/system/framework/:/system/framework/:/system/framework/apache-

:/system/framework/:/system/framework/:/system/framework/:/system/framework/mediatek-telephony-

:/system/framework/dolby_

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

ImageSpace类的静态成员函数GenerateImage实际上就调⽤dex2oat⼯具在/data/dalvik-cache⽬录下⽣成 两个⽂件:system@framework@@

system@framework@@

system@framework@@是⼀个Image⽂件,通过--image选项传递给dex2oat⼯具, ⾥⾯包含了⼀些需要在Zygote进程启动时预加载的类。这些需要预加

载的类由/system/framework/⽂件⾥⾯ preloaded-classes⽂件指定。

system@framework@@是⼀个OAT⽂件,通过--oat-file选项传递给dex2oat 具,它是由系统启动路径中指定的jar⽂件⽣成的。每⼀个jar⽂件都通过⼀

--dex-file选项传递给dex2oat⼯具。这样dex2oat 具就可以将它们所包含的⽂件⾥⾯的DEX字节码翻译成本地机器指令。

这样,我们就得到了⼀个包含有多个DEX⽂件的OAT⽂件system@framework@@

通过上⾯的分析,我们就清楚地看到了ART运⾏时所需要的OAT⽂件是如何产⽣的了。其中,由系统启动类路径指定的DEX⽂件⽣成的OAT⽂件称为类型为 BOOTOAT

件,即⽂件。有了这个背景知识之后,接下来我们就继续分析ART运⾏时是如何加载OAT⽂件的。

art/runtime/

bool Exec(std::vector& arg_vector, std::string* error_msg) {

const std::string command_line(Join(arg_vector, ' '));

CHECK_GE(arg_(), 1U) << command_line;

// Convert the args to char pointers.

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

std::vector<char*> args;

for (size_t i = 0; i < arg_(); ++i) {

const std::string& arg = arg_vector[i];

char* arg_str = const_cast<char*>(arg.c_str());

CHECK(arg_str != nullptr) << i;

_back(arg_str);

}

_back(NULL);

// fork and exec

pid_t pid = fork();

if (pid == 0) {

// no allocation allowed between fork and exec

// change process groups, so we don't get reaped by ProcessManager

setpgid(0, 0);

execv(program, &args[0]);

PLOG(ERROR) << "Failed to execv(" << command_line << ")";

exit(1);

} else {

if (pid == -1) {

*error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",

command_line.c_str(), strerror(errno));

return false;

}

// wait for subprocess to finish

int status;

pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));

if (got_pid != pid) {

*error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "

"wanted %d, got %d: %s",

command_line.c_str(), pid, got_pid, strerror(errno));

return false;

}

if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {

*error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",

command_line.c_str());

return false;

}

}

return true;

}

ART运⾏时提供了⼀个OatFile类,通过调⽤它的静态成员函数Open可以在本进程中加载OAT⽂件,它的实现如下所⽰:

/art/runtime/oat_

OatFile* OatFile::Open(const std::string& filename,

const std::string& location,

byte* requested_base,

bool executable,

std::string* error_msg) {

CHECK(!()) << location;

CheckLocation(filename);

std::unique_ptr ret;

if (kUsePortableCompiler && executable) {

// If we are using PORTABLE, use dlopen to deal with relocations.

//

// We use our own ELF loader for Quick to deal with legacy apps that

// open a generated dex file by name, remove the file, then open

// another generated dex file with the same name.

(OpenDlopen(filename, location, requested_base, error_msg));

} else {

// If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:

//

// On target, dlopen may fail when compiling due to selinux restrictions on installd.

//

// On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.

// This won't work for portable runtime execution because it doesn't process relocations.

std::unique_ptr file(OS::OpenFileForReading(filename.c_str()));

if (() == NULL) {

*error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));

return nullptr;

}

(OpenElfFile((), location, requested_base, false, executable, error_msg));

// It would be nice to unlink here. But we might have opened the file created by the

// ScopedLock, which we better not delete to avoid races. TODO: Investigate how to fix the API

// to allow removal when we know the ELF must be borked.

}

return e();

}

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

return nullptr;

}

return oat_e();

}

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

//zygote64 进程的初始化

01-04 15:39:58.140 394 394 E art : Runtime::Init()

01-04 15:39:58.148 394 394 E art : new gc::Heap()

01-04 15:39:58.151 394 394 E art : space::ImageSpace::Create()

01-04 15:39:58.151 394 394 E art : ImageSpace::Create()...

01-04 15:39:58.178 394 394 E art : ...............

01-04 15:39:58.178 394 394 E art : GenerateImage() .....

01-04 15:39:58.199 394 394 E art : GenerateImage: /system/bin/dex2oat --image=/data/dalvik-cache/arm64/system@framework@ --dex-file=/system/framework/ --dex-file=/system/framework/ --dex-file=/sy

...............................//dex2oat编译image⽂件

01-04 15:41:31.783 394 394 E art : image_space != nullptr

01-04 15:41:31.871 394 394 E art : BlockSignals() and InitPlatformSignalHandlers()

01-04 15:41:31.871 394 394 E art : boot_class_path_string_:/system/framework/:/system/framework/:/system/framework/:/system/framework/:/system/framework/:/system/fram

01-04 15:41:31.871 394 394 E art : class_path_string_:

01-04 15:41:31.871 394 394 E art : image_location_:/system/framework/

01-04 15:41:31.871 394 394 E art : (SIGSTKFLT);

01-04 15:41:31.871 394 394 E art : Runtime::InitPlatformSignalHandlers()

01-04 15:41:31.871 394 394 E art : Has define HAVE_ANDROID_OS

01-04 15:41:31.871 394 394 I art : buildType: userdebug, roAaReport: , roSf: 0

01-04 15:41:31.871 394 394 E art : enableHtcSigHandler == true

01-04 15:41:31.871 394 394 E art : Has define __LP64__

01-04 15:41:31.871 394 394 I art : do sigaltstack at InitPlatformSignalHandlers, size: 12288-byte, ret: 0

01-04 15:41:31.871 394 394 E art : Runtime::InitPlatformSignalHandlers() _sigaction = NativeCrashSigHandler

01-04 15:41:31.871 394 394 E art : InitializeSignalChain()

01-04 15:41:31.871 394 394 E art : fault_()

01-04 15:41:31.871 394 394 E art : SetUpArtAction() action->sa_sigaction = art_fault_handler;

01-04 15:41:31.871 394 394 E art : new StackOverflowHandler

01-04 15:41:31.871 394 394 E art : new NullPointerHandler

01-04 15:41:31.881 394 394 E art : HTC+++ is_zygote_ = true

01-04 15:41:31.881 394 394 E art : GetHeap()->HasImageSpace()

01-04 15:41:31.886 394 394 E art : after initImageSpace

01-04 15:41:31.893 394 394 I art : Runtime::Start Zygote: isShippingRom=0

//dex2oat参数:

GenerateImage:

/system/bin/dex2oat

--image=/data/dalvik-cache/arm64/system@framework@

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/

--dex-file=/system/framework/dolby_

--oat-file=/data/dalvik-cache/arm64/system@framework@

--instruction-set=arm64 --instruction-set-feature

frameworks/base/cmds/app_process/app_

void main() {

//解析虚拟机相关的参数

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

if (zygote) {

("Init", args, zygote);

} else if (className) {

("eInit", 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/

void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)

{

//注册虚拟机创建的相关jni函数,主要是为了JNI_CreateJavaVM函数的调⽤

JniInvocation jni_invocation;

//Init函数会加载库,使⽤dlopen()给函数指针JNI_CreateJavaVM找到对应的接⼝

jni_(NULL);

//创建虚拟机

JNIEnv* env;

if (startVm(&mJavaVM, &env, zygote) != 0) {

return;

}

//注册相关的jni函数

if (startReg(env) < 0) {

ALOGE("Unable to register all android nativesn");

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 {

//找到类的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);

ALOGE("JNI_CreateJavaVM failedn");

return -1;

}

return 0;

}

java_vm_

// 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];

_back(std::make_pair(std::string(option->optionString), option->extraInfo));

}

bool ignore_unrecognized = args->ignoreUnrecognized;

//创建Runtime

if (!Runtime::Create(options, ignore_unrecognized)) {

ATRACE_END();

return JNI_ERR;

}

Runtime* runtime = Runtime::Current();

//调⽤runtime->Start();

bool started = runtime->Start();

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

*p_vm = runtime->GetJavaVM();

return JNI_OK;

}