news 2026/1/21 14:18:15

编译(二):class、dex、so 编译流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
编译(二):class、dex、so 编译流程

编译(一):理论知识

编译(二):class、dex、so 编译流程


Class 流程

  • 加载:查找和导入类的二进制数据
  • 链接:执行验证,准备和(可选)解析
    • 验证:确保导入类型的正确性
    • 准备:为类变量分配内存并将内存初始化为默认值
    • 解析:将符号引用从类型转换为直接引用。
  • 初始化:调用将代码初始化为正确的初始值的Java代码。
  • 加载:将类的信息从文件中获取并且载入到JVM内存中
    1. 通过一个类的全限定名来获取其定义的二进制字节流
    2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
    3. 在Java堆中生成一个代表这个类的 java. lang Class对象,作为对方法区中这些数据的访问入口
  • 验证:检查读入的结构是否符合JVM规范的描述
    1. 为了确保 Class文件中的字节流包含的信息符合当前虚拟机的要求
    2. 文件格式的验证、元数据的验证、字节码验证和符号引用验证
  • 准备:分配内存,初始化变量
  • 解析:把这个类的常量池的所有符号引用改变成直接引用
  • 初始化:执行静态初始化程序、类构造器方法的过程

PathClassLoader 流程

  • 初始化
  • DexPathList.DexPathList
    • dexElements: 根据多路径的分隔符“;”将dexPath转换成File列表,记录所有的dexFile
    • nativeLibraryPathElements: 记录所有的Native动态库, 包括app目录的native库和系统目录的native库。
    • makePathElements
    • makeDexElements 创建Element数组
    • loadDexFile
    • 创建对象DexFile
    • openDexFile
    • dalvik_system_DexFile.DexFile_openDexFileNative
  • ClassLoader.loadClass
    • 判断当前类加载器是否已经加载过指定类,若已加载则直接返回,否则继续执行;
    • 调用parent的类加载递归加载该类,检测是否加载,若已加载则直接返回,否则继续执行;
    • 调用当前类加载器,通过findClass加载。
  • findClass
  • DexPathList.findClass 一个Classloader可以包含多个dex文件,每个dex文件被封装到一个Element对象,这些Element对象排列成有序的数组 dexElements。当查找某个类时,会遍历所有的dex文件,如果找到则直接返回,不再继续遍历dexElements。
  • DexFile.loadClassBinaryName
  • dalvik_system_DexFile.defineClassNative 在native层创建目标类的对象并添加到虚拟机列表

System.loadLibrary 流程

  • System.loadLibrary
  • Runtime.loadLibrary
    • 当loader不为空时, 则通过loader.findLibrary()查看目标库所在路径;
    • 当loader为空时, 则从默认目录mLibPaths下来查找是否存在该动态库;
      • System.initUnchangeableSystemProperties 将大量的key-value对保存到Properties对象, 重点看specialProperties
      • System.parsePropertyAssignments 将assignments数据解析后保存到Properties对象,而此处的assignments来源于java_lang_System.specialProperties()方法
      • linker.do_android_get_LD_LIBRARY_PATH 看kDefaultLdPaths数组
      • linker.kDefaultLdPaths
  • BaseDexClassLoader.findLibrary
    • DexPathList.DexPathList DexPathList初始化
      • dexElements: 记录所有的dexFile文件
      • nativeLibraryPathElements: 记录所有的Native动态库, 包括app目录的native库和系统目录的native库.
    • DexPathList.findLibrary 从所有的动态库nativeLibraryPathElements(包含两个系统路径)查询是否存在匹配的
    • System.mapLibraryName 将动态库的名字转换为so
    • DexPathList.java ::Element.findNativeLibrary 遍历查询,一旦找到则返回所找到的目标动态库
  • Runtime.doLoad 增加同步锁,保证并发时一致性
    • 当loader为空,则ldLibraryPath为系统目录下的Native库
    • 当lodder不为空,则ldLibraryPath为app目录下的native库
    • java_lang_Runtime.Runtime_nativeLoad
      • 调用dlopen函数,打开一个so文件并创建一个handle;
      • 调用dlsym()函数,查看相应so文件的JNI_OnLoad()函数指针,并执行相应函数。
  • android_media_MediaPlayer.JNI_OnLoad
  • android_media_MediaPlayer.register_android_media_MediaPlayer
  • AndroidRuntime.registerNativeMethods
  • JNIHelp.jniRegisterNativeMethods
  • jni.RegisterNatives 这个过程完成了gMethods数组中的方法的映射关系
  • java_vm_ext.LoadNativeLibrary
    • JavaVM:进程虚拟机环境,每个进程有且只有一个JavaVM实例
    • JNIEnv:线程上下文环境,每个线程有且只有一个JNIEnv实例
    • 检查该动态库是否已加载
    • 通过dlopen打开动态共享库
    • 创建SharedLibrary共享库,并添加到libraries_列表
    • 通过dlsym获取JNI_OnLoad符号所对应的方法, 并调用该方法
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/17 8:55:47

导师严选9个AI论文工具,继续教育学生轻松搞定论文写作!

导师严选9个AI论文工具,继续教育学生轻松搞定论文写作! AI 工具助力论文写作,高效又省心 在当今学术研究日益数字化的背景下,AI 工具正逐渐成为学生和科研工作者不可或缺的得力助手。尤其对于继续教育领域的学习者来说&#xff0c…

作者头像 李华
网站建设 2026/1/16 11:25:16

想自定义软件图标?试试exe图标修改器

对于希望自定义电脑上应用程序外观的用户来说,exe图标修改器是一个实用工具。它允许你直接替换Windows可执行文件(.exe)内嵌的图标资源,从而实现软件图标的个性化。无论是想让自己的作品更独特,还是想统一某个软件套装…

作者头像 李华
网站建设 2026/1/15 11:18:33

想搞懂算法效率?先弄明白递归关系的基本形式

递归关系是描述序列各项之间联系的数学方程,它在计算机算法分析和离散数学中扮演着核心角色。理解递归关系,意味着你能够洞察许多算法(如归并排序、斐波那契数列计算)内在的运作规律和效率本质,这对于优化程序性能至关…

作者头像 李华
网站建设 2026/1/19 12:09:17

通孔PCB的5大核心优势

今天就来拆解通孔 PCB 的 5 大核心优势,以及它的典型应用场景,带你重新认识这个 “老牌技术” 的硬核实力。​问 1:通孔 PCB 的第一个核心优势是什么?为什么大功率设备离不开它?答:第一个核心优势是超强的功…

作者头像 李华
网站建设 2026/1/16 16:57:38

从 Chat 到 Agent:Solon AI 带你进入“行动派”大模型时代

在过去的一年里,我们已经习惯了与 AI “聊天”。但当你试图让大模型帮你在数据库查数据、给客户发邮件、或者自动排查系统日志时,你会发现:只会“说”的对话框,无法直接解决复杂的业务逻辑。 大模型需要从“聊天机器人”进化为“智…

作者头像 李华