高雄市网站建设_网站建设公司_Logo设计_seo优化
2026/1/15 11:22:32
网站建设
项目流程
编译(一):理论知识
编译(二):class、dex、so 编译流程
Class 流程
- 加载:查找和导入类的二进制数据
- 链接:执行验证,准备和(可选)解析
- 验证:确保导入类型的正确性
- 准备:为类变量分配内存并将内存初始化为默认值
- 解析:将符号引用从类型转换为直接引用。
- 初始化:调用将代码初始化为正确的初始值的Java代码。
- 加载:将类的信息从文件中获取并且载入到JVM内存中
- 通过一个类的全限定名来获取其定义的二进制字节流
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
- 在Java堆中生成一个代表这个类的 java. lang Class对象,作为对方法区中这些数据的访问入口
- 验证:检查读入的结构是否符合JVM规范的描述
- 为了确保 Class文件中的字节流包含的信息符合当前虚拟机的要求
- 文件格式的验证、元数据的验证、字节码验证和符号引用验证
- 准备:分配内存,初始化变量
- 解析:把这个类的常量池的所有符号引用改变成直接引用
- 初始化:执行静态初始化程序、类构造器方法的过程
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符号所对应的方法, 并调用该方法