Android ART虚拟机 启动和初始化
前言
之前整理了一系列Dalvik虚拟机的关于堆内存和GC的文章,轮到对ART内存进行分析优化了,继续整理输出一波,本篇为ART虚拟机系列的第一篇,介绍ART虚拟机的启动和初始化。
ART启动
app_main启动
frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));if (zygote) {runtime.start("com.android.internal.os.ZygoteInit", args);} else if (className) {runtime.start("com.android.internal.os.RuntimeInit", args);} else {return 10;}
}
AndroidRuntime.cpp
frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{/* start the virtual machine */JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;if (startVm(&mJavaVM, &env) != 0) {return;}onVmCreated(env);/** Register android functions.*/if (startReg(env) < 0) {return;}
}int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{// 拼接一大堆参数if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {ALOGE("JNI_CreateJavaVM failed\n");goto bail;}
}
JniInvocation.cpp
libnativehelper/JniInvocation.cpp,
5.x的代码里获取libart.so,再获取到JNI_CreateJavaVM、JNI_GetCreatedJavaVMs等的实现。
static const char* kLibraryFallback = "libart.so";bool JniInvocation::Init(const char* library) {library = GetLibrary(library, buffer);handle_ = dlopen(library, RTLD_NOW);if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),"JNI_GetDefaultJavaVMInitArgs")) {return false;}if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),"JNI_CreateJavaVM")) {return false;}if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),"JNI_GetCreatedJavaVMs")) {return false;}return true;
}extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* vm_args) {return JniInvocation::GetJniInvocation().JNI_GetDefaultJavaVMInitArgs(vm_args);
}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);
}extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count) {return JniInvocation::GetJniInvocation().JNI_GetCreatedJavaVMs(vms, size, vm_count);
}
jni_internal.cc
art/runtime/jni_internal.cc
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);// 创建虚拟机if (!Runtime::Create(options, ignore_unrecognized)) {return JNI_ERR;}Runtime* runtime = Runtime::Current();runtime->Start();*p_env = Thread::Current()->GetJniEnv();*p_vm = runtime->GetJavaVM();return JNI_OK;
}
art初始化
art/runtime/runtime.h
art/runtime/runtime.cc
runtime.h
class Runtime {public:// Creates and initializes a new runtime.static bool Create(const RuntimeOptions& options, bool ignore_unrecognized)SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);// Starts a runtime, which may cause threads to be started and code to run.bool Start() UNLOCK_FUNCTION(Locks::mutator_lock_);static Runtime* Current() {return instance_;}gc::Heap* GetHeap() const {return heap_;}~Runtime();private:Runtime();void BlockSignals();bool Init(const RuntimeOptions& options, bool ignore_unrecognized)SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);// A pointer to the active runtime or NULL.static Runtime* instance_;gc::Heap* heap_;
}
Runtime::Create
bool Runtime::Create(const RuntimeOptions& options, bool ignore_unrecognized) {if (Runtime::instance_ != NULL) {return false;}instance_ = new Runtime;instance_->Init(options, ignore_unrecognized);return true;
}
Runtime()
Runtime::Runtime(): is_zygote_(false),is_concurrent_gc_enabled_(true),is_explicit_gc_disabled_(false),dex2oat_enabled_(true),default_stack_size_(0),heap_(nullptr),monitor_list_(nullptr),monitor_pool_(nullptr),thread_list_(nullptr),class_linker_(nullptr),signal_catcher_(nullptr),java_vm_(nullptr) {
}
Runtime::Init
bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) {Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_);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_);dump_gc_performance_on_shutdown_ = options->dump_gc_performance_on_shutdown_;BlockSignals();InitPlatformSignalHandlers();InitializeSignalChain();java_vm_ = new JavaVMExt(this, options.get());Thread::Startup();class_linker_ = new ClassLinker(intern_table_);//...return true;
}
runtime->start
bool Runtime::Start() {// Restore main thread state to kNative as expected by native code.Thread* self = Thread::Current();self->TransitionFromRunnableToSuspended(kNative);started_ = true;if (IsZygote()) {ScopedObjectAccess soa(self);gc::space::ImageSpace* image_space = heap_->GetImageSpace();if (image_space != nullptr) {Runtime::Current()->GetInternTable()->AddImageStringsToTable(image_space);Runtime::Current()->GetClassLinker()->MoveImageClassesToClassTable();}}// InitNativeMethods needs to be after started_ so that the classes it touches will have methods linked to the oat file if necessary.InitNativeMethods();// Initialize well known thread group values that may be accessed threads while attaching.InitThreadGroups(self);Thread::FinishStartup();system_class_loader_ = CreateSystemClassLoader();StartDaemonThreads();finished_starting_ = true;return true;
}
相关文章:
Android ART虚拟机 启动和初始化
前言 之前整理了一系列Dalvik虚拟机的关于堆内存和GC的文章,轮到对ART内存进行分析优化了,继续整理输出一波,本篇为ART虚拟机系列的第一篇,介绍ART虚拟机的启动和初始化。 #mermaid-svg-8iNdLFTpOHLgRjHA {font-family:"tre…...
宇视科技一二三面
一面 1、自我介绍 2、堆和栈的区别,堆在数据结构中是如何表示的 3、有用过Linux吗?虚拟空间中用户态是3G,假如计算机的内存是4G,为什么计算机可以运行这些进程 4、虚拟地址到物理地址的映射过程 5、进程间的通信方式 6、共享内存…...

优思学院|盘点,精益生产25个工具!【必需收藏】
精益生产方法需要一种全面的方法才能有效实施。精益这个概念是每个接触产品供应链的人都要实践的,无论是在计划方面还是在分析方面。 精益生产工具有助于持续改进生产效率和产品或服务质量。精益工具是要减少 Muda (浪费),从生产过…...

Linux中将多块新硬盘合并成一个,挂载到/mysqldata目录下
需求: 将两块空硬盘合并为“一块”,挂载到指定目录(/data)下,达到在一个目录使用2块硬盘所有空间的效果。 使用 fdisk -l 命令查看当前系统中的硬盘,如下图: 系统中存在两块未分配的硬盘&#…...

Git的SSH密钥配置
Git的SSH密钥配置简记Githttps和ssh的区别基本需求SSH密钥类型ED25519 SSH 密钥RSA SSH 密钥查看您是否有现有的 SSH 密钥对设置流程设置user name和emailssh密钥配置检查是否存在ssh Key创建新的ssh key将ssh密钥添加到您的Git帐户验证您是否可以连接使用Git有一段时间了&…...

C++回顾(九)——多继承
9.1 多继承 9.1.1 概念 一个类有多个直接基类的继承关系称为多继承(多个父类)多继承声明语法 class 派生类名 : 访问控制 基类名1 , 访问控制 基类名2 , … , 访问控制 基类名n {数据成员和成员函数声明 };类 C 可以根据访问控制同时…...
交流约瑟夫森效应
定理 根据约瑟夫森效应的基本方程,当隧道结两端施加恒定电压V0V_0V0时,结两边超导体波函数的位相差为 Δϕ2eℏV0tΔϕ0\begin{align} \Delta\phi\frac{2e}{\hbar}V_0t\Delta\phi_0 \end{align} Δϕℏ2eV0tΔϕ0 得到超导电流密度为 JsJcs…...

大数据项目实战之数据仓库:用户行为采集平台——第3章 用户行为日志
第3章 用户行为日志 3.1 用户行为日志概述 用户行为日志的内容,主要包括用户的各项行为信息以及行为所处的环境信息。收集这些信息的主要目的是优化产品和为各项分析统计指标提供数据支撑。收集这些信息的手段通常为埋点。 目前主流的埋点方式,有代码…...

centos6下为Rstudio安装多版本R
之前的R版本太旧,不少包装不上,需要安装新版本的R: R --version R version 3.6.0 (2019-04-26) -- "Planting of a Tree"于是下载最新版R: 因为没有证书,需要加上最后面的参数. wget https://mirrors.tuna.tsinghua.edu.cn/CRAN/src/base/R-4/R-4.2.2.tar.gz --no…...

TCL 拥抱云原生,实现 IT 成本治理优化
作者:行疾 TCL 工程师团队基于阿里云企业云原生 IT 成本治理方案沉淀了一套成熟的 IT 企业成本治理流程与系统,通过阿里云容器服务提供的开箱即用的成本洞察、资源智能画像等功能,进行业务成本拆分、闲置资源可视化发现,并制定弹性…...

什么是API接口
API接口是指应用程序接口,是一种让不同的应用程序之间进行数据交互的方式。在现代软件开发中,API接口已经成为了必不可少的一部分。它们让开发者们可以将不同的功能组合在一起,同时也让不同的应用程序之间可以相互连接和通讯。API接口的作用A…...

基于单片机的波形发生器设计
单片机可以用来设计各种类型的波形发生器,下面是一种基于单片机的波形发生器设计方案。所需材料:单片机:可以选择常见的Atmel AVR单片机,如ATmega328P等。调制器:可以使用AD9833或AD9851等常用的调制器。时钟ÿ…...
phpmyadmin SQL注入 (CVE-2020-5504)
文章目录 0x01 漏洞介绍0x02 影响版本0x03 漏洞编号0x04 漏洞查询0x05 漏洞环境0x06 漏洞复现方法一:写入shell方法二:报错注入0x07 修复建议免责声明摘抄0x01 漏洞介绍 phpMyAdmin是phpMyAdmin团队的一套免费的、基于Web的MySQL数据库管理工具。该工具能够创建和删除数据库,…...

华为机试题:HJ107 求解立方根(python)
文章目录(1)题目描述(2)Python3实现(3)知识点详解1、input():获取控制台(任意形式)的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方…...

论文公式符号规范
参考自1,记录论文公式的符号规范: 1.变量和公式符号表达 物理量 物理量符号用英文斜体字母或希腊斜体字母,表示物理量大小用数字加单位,单位使用正体。 例如: m10.05gx10.12ζ35.36mVm10.05 \mathrm{~g} \quad x10…...
哈工大面向服务的软件系统 期末开卷提纲
引言本课程期末考试为开卷,博主2022年期末卷面94/100,总分92.9排名第2/82,现分享复习提纲以供学弟学妹们参考。本提纲仅供参考,切勿进行其他目的的使用。基于2021秋季考试题的思考一、Spring Boot的优点是:1. 非常快速…...

Adding Conditional Control to Text-to-Image Diffusion Models
安全验证 - 知乎知乎,中文互联网高质量的问答社区和创作者聚集的原创内容平台,于 2011 年 1 月正式上线,以「让人们更好的分享知识、经验和见解,找到自己的解答」为品牌使命。知乎凭借认真、专业、友善的社区氛围、独特的产品机制…...

C++从头再来:知识点速通
1. 关于scanf 1.1 读入数字 scanf 的返回值表示成功输入的变量个数,当输入结束时,scanf将无法再次读取数据,返回0 # include <stdio.h> # include <math.h> # include <time.h># define M 1000000; // compute the max,…...

LearnDash Groups学习群组:您需要了解的一切
大约131k 网站使用 LearnDash。因此,毫无疑问,LearnDash是 WordPress 领域中最受欢迎的 LMS。而且,这是因为它具有强大的功能。但让它更受欢迎的是它与大多数第 3 方扩展很好地集成,并且比现有的任何其他 LMS 都更灵活。群组和群组…...
软件开发过程中遇到一个傻嘚业主能让你抓狂
背景 之前的一个网站交付了之后,业主一直未验收,今天忽然间开始了他的扯淡需求调整。 问题1 有一个问题是pdf文件上传显示问题,目前是pdf有一个封面要上传,排序字段可自动调整控制。但是就这么好用的功能,被他给pas…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...

tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...