2023年11月29日发(作者:)
JNI_CreateJavaVM(Runtime::Create())
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
前⾯的关键字service告诉init进程创建⼀个名为"zygote"的进程,这个zygote进程要执⾏的程序是/system/bin/app_process,后⾯是要传给app_process的参数。
/frameworks/base/cmds/app_process/app_
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
{
/* 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
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
// 第⼀⼤步:创建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
std::vector
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(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(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
}
}
// 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
Split(boot_class_path_string, ':', boot_class_path);
......
std::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⽂件称为类型为 BOOT的OAT⽂
件,即⽂件。有了这个背景知识之后,接下来我们就继续分析ART运⾏时是如何加载OAT⽂件的。
art/runtime/
bool Exec(std::vector
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
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
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
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
{
//注册虚拟机创建的相关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
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;
}


发布评论