Android Dalvik虚拟机 启动和初始化

2023/9/30 16:40:48

前言

最近因工作需要,阅读了一些Dalvik虚拟机代码,整理输出一波。本文整理Dalvik虚拟机在启动流程和初始化流程,为下篇分析Dalvik的内存分配流程和gc流程打一个基础。
本系列代码均基于4.4.2分析。

Dalvik虚拟机启动流程

Android Rumtime.cpp Jni.cpp init.cpp JNI_CreateJavaVM dvmCreateJNIEnv dvmStartup dvmGcStartup、dvmThreadStartup... initZygote Android Rumtime.cpp Jni.cpp init.cpp

AndroidRuntime.cpp

/*
 * Start the Dalvik Virtual Machine.
 *
 * Various arguments, most determined by system properties, are passed in.
 * The "mOptions" vector is updated.
 *
 * Returns 0 on success.
 */
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) {
	// 拼接一大堆虚拟机初始化参数
	// adb shell getprop | grep dalvik 通过该命令可以查看一些
	/*
     * Initialize the VM.
     *
     * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
     * If this call succeeds, the VM is ready, and we can start issuing
     * JNI calls.
     */
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        goto bail;
    }
    result = 0;
bail:
    free(stackTraceFile);
    return result;
}

Jni.cpp

/*
 * Create a new VM instance.
 *
 * The current thread becomes the main VM thread.  We return immediately,
 * which effectively means the caller is executing in a native method.
 */
jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
	// 初始化gDvm全局变量
	memset(&gDvm, 0, sizeof(gDvm));
	// 初始化JavaVmExt
	JavaVMExt* pVM = (JavaVMExt*) calloc(1, sizeof(JavaVMExt));
    pVM->funcTable = &gInvokeInterface; // jni表
	// Create a JNIEnv for the main thread.  
	JNIEnvExt* pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);
	// 启动虚拟机
	dvmStartup(argc, argv.get(), args->ignoreUnrecognized, (JNIEnv*)pEnv);
	return JNI_OK;
}

init.cpp

在init.cpp中做Dalvik虚拟机初始化操作。

/*
 * VM initialization.  Pass in any options provided on the command line.
 * Do not pass in the class name or the options for the class.
 *
 * Returns 0 on success.
 */
std::string dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized, JNIEnv* pEnv) {
	/*
     * Initialize components.
     */
     // 初始化Davlik的内存分配记录模块AllocTracker。
     dvmAllocTrackerStartup();
     // 初始化Dalvik的垃圾回收模块。内部包含堆初始化
     dvmGcStartup();
     // 初始化Davlik的线程管理模块。Dalvik线程就是Linux的线程,线程管理模块只是用Thread类来记录Dalvik与线程相关的数据。所有Thread类会形成一个链表。这里除了初始化链表外,还会为主线程创建一个Thread类,并把它加入到链表中。
     dvmThreadStartup();
     // 初始化Davlik的内部native函数模块
     dvmInlineNativeStartup();
     // 初始化Dalvik的寄存器映射模块Register Map
     dvmRegisterMapStartup();
     // 初始化Dalvik的instanceof操作符缓存模块
     dvmInstanceofStartup();
     // 初始化Dalvik的类装载模块,类装载模块主要负责装载和查找Java类
     dvmClassStartup();
     // 初始化gDvm中定义的所有Java关键字的类
	 dvmFindRequiredClassesAndMembers()
	 // 初始化Dalvik的常量字符串模块。Dalvik在装载类时,会把类中定义的各种字符串都放入gDvm的两个hash表internedStrings和literalStrings中。Dalvik内部创建相同字符串的对象时只会产生引用而不再创建对象了,这样就能节约重复字符串占用的内存。
	 dvmStringInternStartup();
	 // 初始化Dalvik的native函数管理模块
	 dvmNativeStartup();
	 // 初始化Dalvik内部类的native函数模块。这个模块定义了所有Dalvik的内部类的native函数表。如DexFile、VMRuntime、DexFile等
	 dvmInternalNativeStartup();
	 // 初始化Dalvik的JNI模块。主要是创建了全局引用表和全局弱引用表
	 dvmJniStartup();
	 // 这个函数的作用是初始化类java.lang.Class
	 dvmInitClass();
	 // 注册com.android.dex.Dex的native方法getDex()。同时装载JNI库libjavacore.so以及libnativehelper.so
	 registerSystemNatives();
	 // 。创建一些异常对象,包括OutOfMemoryError、InternalError和NoClassDefFoundError,保存在gDvm中
	 dvmCreateStockExceptions();
	 // 执行java.lang.Daemons的start()方法来启动和初始化垃圾回收线程
	 dvmGcStartupClasses();
    
    // 虚拟机OK了,zygote再继续启动
    initZygote();
}

重要变量gDvm

在dalvik/vm/Globals.h头文件中定义,里面参数太多了,列出了如下一般开发涉及的重要变量。
这种变量是全局变量,可以通过dlsys获取到,再获取其内部的参数,在hook时经常用到。

/* global state */
struct DvmGlobals gDvm;

/*
 * All fields are initialized to zero.
 *
 * Storage allocated here must be freed by a subsystem shutdown function.
 */
struct DvmGlobals {
	// 几个最基本的jar包的路径。包括core.jar、ext.jar、framework,jar、services.jar和android.policy.jar
    char*       bootClassPathStr;
    // 存放系统jar包的路径。通常为/system/framework
    char*       classPathStr;
	
	// 堆初始化参数,下篇再讲
    size_t      heapStartingSize;
    size_t      heapMaximumSize;
    size_t      heapGrowthLimit;
    bool        lowMemoryMode;
    double      heapTargetUtilization;
    size_t      heapMinFree;
    size_t      heapMaxFree;
    size_t      stackSize;
    size_t      mainThreadStackSize;
	
	/*
     * Loaded classes, hashed by class name.  Each entry is a ClassObject*,
     * allocated in GC space.
     */
	HashTable*  loadedClasses;
	/* Hash table of strings interned by the user. */
    HashTable*  internedStrings;
    /* Hash table of strings interned by the class loader. */
    HashTable*  literalStrings;
    /*
     * Thread list.  This always has at least one element in it (main),
     * and main is always the first entry.
     */
	Thread*     threadList;
    /*
     * JNI global reference table.
     */
    IndirectRefTable jniGlobalRefTable;
    IndirectRefTable jniWeakGlobalRefTable;
    pthread_mutex_t jniGlobalRefLock;
    pthread_mutex_t jniWeakGlobalRefLock;
    /*
     * Native shared library table.
     */
    HashTable*  nativeLibs;

    /*
     * GC heap lock.  Functions like gcMalloc() acquire this before making
     * any changes to the heap.  It is held throughout garbage collection.
     */
    pthread_mutex_t gcHeapLock;
    /*
     * Condition variable to queue threads waiting to retry an
     * allocation.  Signaled after a concurrent GC is completed.
     */
    pthread_cond_t gcHeapCond;
    /* Opaque pointer representing the heap. */
    GcHeap*     gcHeap;

    /* Monitor list, so we can free them */
    /*volatile*/ Monitor* monitorList;
}
extern struct DvmGlobals gDvm;

http://www.jnnr.cn/a/273028.html

相关文章

Windows常用小技巧集锦(持续更新ing...)

诸神缄默不语-个人CSDN博文目录 本文介绍一些在Windows系统的学习与使用过程中&#xff0c;会碰到的小问题和解决方案。 最近更新时间&#xff1a;2023.2.5 最早更新时间&#xff1a;2023.2.5 windows系统下使用cd命令_龙虾小兵的博客-CSDN博客_cd windows解决win10快速访问…

软件测试(概念Ⅰ) · 软件测试的基本概念 · 什么是需求 · 测试用例的概念 · 软件错误(bug)的概念

一、什么是软件测试软件测试和开发的区别测试和调试的区别一个优秀的软件测试人员具备的素质二、什么是需求从测试人员角度看待需求三、测试用例的概念四、软件错误&#xff08;bug&#xff09;的概念一、什么是软件测试 最常见的解释是&#xff1a;软件测试就是找 BUG&#x…

【Java集合】LinkedHashMap源码详解

目录 一、介绍 1.1 LinkedHashMap简介 1.2 继承关系 二、数据结构 2.1 成员属性 2.2 内部类 2.3 存储结构 三、源码分析 3.1 构造方法 3.2 LinkedHashMap的init()方法 3.3 维护链表的操作 3.3.1 afterNodeRemoval(Node e)方法,v> 3.3.2 afterNodeInsertion(boolean evict)方…

2023-02-04 Elasticsearch 倒排索引的理解 Trie前缀树原理

1 搜索引擎 引出倒排表的原理 全文搜索引擎 自然语言处理(NLP) 、爬虫、网页处理、大数据处理 如谷歌、百度、搜狗、必应等等 垂直搜索引擎 有明确搜索目的的搜索行为 如各大电商网站、OA、站内搜索、视频网站等 要求&#xff1a; 查询快 &#xff08;高效的压缩算法 快速的编码…

图论(8)LCA

一、概念 给定一棵有根树&#xff0c;若节点z既是x的祖先&#xff0c;又是y的祖先&#xff0c;则称z是x和y的公共祖先。 在所有公共祖先中&#xff0c;深度最大的一个为最近公共祖先。 求最近公共祖先的方法有&#xff1a; &#xff08;1&#xff09;&#xff1a; 1.x向上走…

人工智能轨道交通行业周刊-第32期(2023.1.30-2.5)

本期关键词&#xff1a;智能装车系统、南昌地铁巡检机器人、中国铁道学会科学技术奖、AIGC报告、智慧城市 1 整理涉及公众号名单 1.1 行业类 RT轨道交通中关村轨道交通产业服务平台人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交…

配置安全的linux-apache服务器(5)

实验简介 实验所属系列&#xff1a;Linux网络服务配置与安全 实验对象&#xff1a; 本科/专科信息安全专业、网络工程 相关课程及专业&#xff1a;系统安全配置、服务器配置、计算机网络 实验时数&#xff08;学分&#xff09;&#xff1a;2学时 实验类别&#xff1a;实践实验…

删除文件还有救吗?9个最好数据恢复软件你值得尝试

数据恢复软件是一种程序&#xff0c;可帮助从意外删除的存储设备中恢复数据。在这篇博文中&#xff0c;我们彻底研究并生成了适用于 Windows PC 的最佳数据恢复软件列表。我们推荐 奇客数据恢复 作为适用于 Windows 的最佳数据恢复软件。因为它带有不同的扫描模式和选项&#x…

axios中params和data的区别

在开发项目的过程中我们往往忽略了一点&#xff0c;请求接口的传参方式&#xff0c;习惯了post请求就用data,get请求就用params。 params是添加到url的请求字符串中的&#xff0c;用于get请求。服务器并不会读取http body里面的数据,这样我们传递的就是Params里的请求的参数了。…

面试官:Exception和Error有什么区别?

回答思路&#xff1a; 相同点和不同点 异常的分类 异常处理关键字 异常处理的原则 回答总结&#xff1a; 首先相同点是Exception和Error都继承了Throwable类&#xff0c;而不同的是Exception 和 Error 体现了不同异常情况的分类。可以说Error是天灾&#xff0c;出现了也恢复不…

C++基础(4) - 运算符

文章目录输入输出浅谈1、cout 进行 C 输出1.1 控制符 endl1.2 使用 cout 进行拼接2、cin 获取键盘输入常用运算符分类算术运算符1、除法&#xff08;/&#xff09;2、求模&#xff08;%&#xff09;3、自增和自减赋值运算符关系运算符逻辑运算符三元运算符位运算符1、原码、反码…

Java开发学习(四十二)----MyBatisPlus查询语句之条件查询

一、条件查询的类 MyBatisPlus将书写复杂的SQL查询条件进行了封装&#xff0c;使用编程的形式完成查询条件的组合。 这个我们在前面都有见过&#xff0c;比如查询所有和分页查询的时候&#xff0c;都有看到过一个Wrapper类&#xff0c;这个类就是用来构建查询条件的&#xff0…

springboot,vue教务管理系统

开发工具&#xff1a;IDEA服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7前端技术&#xff1a;vue elementUI服务端技术&#xff1a;springbootmybatis本系统拥有三种角色&#xff1a;管理员、教师和学生&#xff0c;项目…

RL笔记:动态规划(1): 策略估计和策略提升

目录 0. 前言 (4.1)策略估计&#xff0c;Policy Evaluation(Prediction) Example 4.1 (python代码) Exercise 4.1 Exercise 4.2 Exercise 4.3 (4.2)Policy Improvement 0. 前言 Sutton-book第4章&#xff08;动态规划&#xff09;学习笔记。本文是关于其中4.1节&#xf…

fpga图像处理(sobel算子)

【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 关于sobel算子,前面已经讲过计算方法了。一种是上下的sobel算子,一种是左右的sobel算子,两者都相当于prewitt算子的进一步拓展。当然,之前的实现方法都是基于python和opencv实现…

Cadence PCB仿真 使用 Allegro PCB SI 为电源网络分配电压并选择仿真的电源网络的方法图文教程

🏡《总目录》   🏡《分目录》 目录 1,概述2,分配电压3,选择仿真网络4,总结1,概述 进行电源分配网络PDN的仿真前,需要进行一些准备工作。首先需要为电源网络分配适合的电压,并选择需要进行PDN分析的网络。本文介绍其具体方法。 2,分配电压 第1步:执行Analyze→P…

TensorFlow Serving模型部署

7.7 TensorFlow Serving模型部署 学习目标 目标 无应用 应用TensorFlow Serving完成模型服务运行 7.7.1 TensorFlow Serving TensorFlow Serving是一种灵活的高性能服务系统&#xff0c;适用于机器学习模型&#xff0c;专为生产环境而设计。TensorFlow Serving可以轻松部署新…

OpenGL | OpenGL 绘制其他图形

一、绘制点GL_POINTSOpenGL默认绘制的点大小是1px&#xff0c;可以使用glPointSize()来改变点的大小&#xff0c;但是要注意&#xff1a;glPointSize()不能放在glBegin()和glEnd()之间&#xff0c;要放在glBegin()之前。1.代码void Draw() {glClearColor(1, 1, 1, 1.0f); //白…

大数据之HBase基础

文章目录前言一、HBase基础简介&#xff08;一&#xff09;基础介绍&#xff08;二&#xff09;应用场景&#xff08;三&#xff09;特点二、数据模型&#xff08;一&#xff09;行键&#xff08;row key&#xff09;&#xff08;二&#xff09;列&#xff08;三&#xff09;列…

(深度学习快速入门)第四章第三节:卷积层详解1

文章目录一&#xff1a;什么是卷积运算&#xff08;了解&#xff09;二&#xff1a;从全连接层到卷积层&#xff08;1&#xff09;解决空间不变性&#xff08;2&#xff09;解决参数爆炸-稀疏连接和权值共享三&#xff1a;CNN中的图像卷积卷积层&#xff1a;卷积层是CNN中的核心…
最新文章