我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android中的类文件和类加载器详情

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android中的类文件和类加载器详情

目录

一、Java中的类加载器

二、Android中的类加载器

2.1 BootClassLoader

2.2 PathClassLoader

2.3 DexClassLoader

2.4 InMemoryDexClassLoader

三、Dex文件

3.1 Android内存中的Dex文件

3.2 Dex文件的生成

一、Java中的类加载器

首先花点时间回顾一下Java中的三种类加载器:

BootStrap ClassLoader 启动类加载器,它是实现自C/C++的类加载器,用于加载JDK的核心类库,例如

java.lang
java.util
等系统类。JVM的启动需要通过BootStrap ClassLoader来创建一个初始类来完成

Extensions ClassLoader 扩展类加载器,ExtClassLoader,它用于加载一些系统之外的额外功能。

Application ClassLoader 应用类加载器,也称作系统类加载器,它可以通过getSystemClassLoader拿到,也可以称为系统类加载器。

Custom ClassLoader 自定义类加载器,我们可以通过继承

java.lang.ClassLoader类
来实现自己的类加载器,注意,ExtClassLoader和AppClassLoader也是继承自
java.lang.ClassLoader类
的。

总体的加载关系是:null->ExtClassloader->AppClassLoader,需要注意的是,BootStrap ClassLoader无法在Java中通过.class.getClassLoader()访问它的父加载器。

同时,这只代表加载关系,而不代表继承关系,ClassLoader的继承关系如下:

其中:

ClassLoader本身是一个抽象类,定义了主要的一些功能。

SecureClassLoader扩展实现了ClassLoader方面加入权限方面的功能,加强了ClassLoader的安全性。

URLClassLoader通过URL路径,从Jar文件和文件夹下加载类和资源。

ExtClassLoader和AppClassLoader,本身都是Launcher应用的内部类,Launcher是Java虚拟机的入口应用,二者都在Launcher中初始化;

双亲委派机制,大致意思就是当一个类加载器去加载某个类时,会优先委托给父加载器去进行加载,而不是自己加载。这样能够有效地保护加载类的安全性,比如我们希望加载一个

java.lang.String
类,在双亲委派机制下,我们就会优先由父类进行加载,而不是我们自己的类加载器去做加载,父类加载器会从指定的,安全的目录下查找String类。如果是我们自己的类加载器中加载该类那么可能会出现一些安全方面的问题。换句话说,你自己定义的
java.lang.String
类是无法被加载的。当然,这个前提是,你得遵循双亲委派机制,如果你重新写个类加载器,自定义了loadClass并且不遵循双亲委派机制,那么双亲委派机制就被打破了。这也是为什么,JVM认为两个类相等不仅仅要类名相等,而且要类加载器相等才是同一个类。

二、Android中的类加载器

区别于标准JVM以Class文件为输入的字节码文件,Android虚拟机采用更为紧凑的Dex文件作为输入文件,无论是Dalvik VM还是ART VM。这样一来,类加载器自然也会有所改变。

Android中的类加载器类型被分为两类:

系统类加载器:PathClassLoader、DexClassLoader、BootClassLoader

自定义类加载器

2.1 BootClassLoader

Android 系统启动时,会使用BootClassLoader来加载常用的类,与SDK中的BootStrap ClassLoader不同的是,它本身不是由C/C++实现的, 而是采用Java实现的,它是ClassLoader的内部类,继承自ClassLoader,本身是一个单例类。应用中无法直接访问到BootClassLoader。

BootClassLoader是在ZygoteInit的入口方法中,间接调用了preloadClasses方法中,进行创建的,Android在

/framework/base/preloaded-classes
中封装了一系列的预加载类的目录,一些常用类,例如:ContextImpl、Fragment、Dialog等等都在列。预加载之后,应用程序启动时,就不用额外去做加载了。

2.2 PathClassLoader

PathClassLoader它通常被系统用来加载Apk中自带的Dex文件,它的构造函数中少了一个参数:optimizedDirectory,这是因为PathClassLoader定义了默认的optimizedDirectory参数:

/data/dalvik-cache/
,因此,我们无法自定义Dex文件的解压路径,所以我们加载类时,一般都使用DexClassLoader

PathClassLoader是Zygote进程在fork SystemServer进程时创建的,当Zygote进程在新创建SystemServer时,通过调用forkSystemServer方法时,会调用到handleSystemServerProcess(),然后调用createPathClassLoader()去创建PathClassLoader。

2.3 DexClassLoader

可以在磁盘中加载.dex或者是.apk文件,但是本质上都是加载属于Android 的字节码文件:Dex文件。

它的构造方法有四个参数:

dexPath:相关的文件路径;支持多个路径,使用「:」分割

optimizedDirectory:Dex文件解压后的文件存储路径,一般情况下使用当前文件的私有路径。

"this parameter is deprecated and has no effect since API level 26."

注意:optimizedDirectory参数在API26之后被废弃了

librarySearchPath:包含C/C++库的路径集合,可以为null

parent:父加载器

我们通常在App启动时,我们通常使用DexClassLoader动态加载Dex的方式来实现应用程序Java代码层面的热修复。

2.4 InMemoryDexClassLoader

Android8.0 中新增的用于加载内存中的类加载器。和PathClassLoader、DexClassLoader一样,都是BaseDexClassLoader的实现类。

三、Dex文件 3.1 Android内存中的Dex文件

BaseDexClassLoader有三个子类:DexClassLoader、PathClassLoader、InMemoryDexClassLoader,它们三个主要任务就是:加载外部的Dex文件,获取其中定义的类信息。同样,Android的类加载机制也遵循双亲委派机制

BaseDexClassLoader有一个特殊的结构:DexPathList类型的pathList ,它内部维护了一个Element类型的数组,用来存储被加载的Dex文件信息:

private Element[] dexElements;

每当我们要使用一个类时,类加载器就会先检索:DexPathList中的所有Dex文件,逐个遍历,看看其中是否含有所需要的类:

Element内部有一个对象:DexFile,在调用Element#findClass时,会按照如下规则去查找:

而最终,loadClassBinaryName会调用Native代码在本地内存上创建一个指向Dex文件的对象,这样 ,我们知道Dex文件在内存中的引用是类加载下的DexPathList中的一个个Element。

这个Element数组可以作为一个热修复的接入点,我们知道,类加载只会被加载一次,如果此时我们有多个Dex文件,那么Dex文件的引用在Element中会按照加载的顺序排列,这样一来,排在前面的Dex类中的Class就会被优先加载,由此我们就可以将热修复后重新生成的

Patch.dex
Patch.apk
加载到用户手机存储空间当中,然后自行使用DexPathClassLoader进行加载,并通过反射,Hook掉PathClassLoader,将
Patch.dex
对应的Element反射插入到其DexPathList当中去。这样一来,加载时就会优先从
Patch.dex
中加载了,原理大致如下图。修复后加载原先出错的类ClassE将会从Patch.dex中优先加载,而出错的Class E由于类加载的特性,将不会被加载出来。

3.2 Dex文件的生成

我们所编写的Java代码,使用Java自带的编译器编译完成之后默认的输出一定是.class文件,而在ART或者Dalvik虚拟机中需要输入Dex文件,那么在其中必然存在Class -> Dex文件的过程。

该过程是由d8工具完成的,在我们的SDK目录下:

/Library/Android/sdk/build-tools/28.0.3
,有非常多和我们Android 构建相关的一些工具,例如aapt2工具会负责将res.xml中的文件在R.java中生成对应的ID引用、负责将二进制资源、资源表resources.arsc、classes.dex以及assets集成打包进一个未签名的.apk文件内。

d8工具会将需要打包的.class文件、额外依赖的Jar文件一同参与编译。比如我们需要对appt2下的一个MainActivity.class文件进行编译,那么我们可以在一个新项目中,点击Android Studio的编译或者上面的绿色小锤子,然后在:

MyApplication2/app/build/intermediates/javac/debug/classes/com/red/myapplication
 下我看到MainActicity.class文件,然后在该目录下执行如下的指令,注意,将MainActivity的AppcompatActivity换成Activity,因为前者是属于AndroidX系列的的AAR包中的依赖,需要额外添加。

d8 aapt/MainActivity.class
 --lib /Library/Android/sdk/platforms/android-29/android.jar
 --output ./

其中,

--lib
指定了一些额外的依赖,因为MainActivity中会依赖
android.jar
中的一些文件(比如Activity类),完成后,我们就得到了一个classes.dex文件,结构如下:

如上的步骤都在Android提供的Gradle套件中,帮我们完成了,Gradle插件依赖的本质,就是插件文件的下载(Gradle同步)和引用。

到此这篇关于Android 中的类文件和类加载器详情的文章就介绍到这了,更多相关Android 类文件 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android中的类文件和类加载器详情

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android中的类文件和类加载器详情

目录一、Java中的类加载器二、Android中的类加载器2.1 BootClassLoader2.2 PathClassLoader2.3 DexClassLoader2.4 InMemoryDexClassLoader三、Dex文件3.
Android中的类文件和类加载器详情
2022-06-07

Android中的类文件和类加载器实例分析

本篇内容介绍了“Android中的类文件和类加载器实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、Java中的类加载器首先花点时间
2023-06-30

Android中怎么利用HttpUrlConnection类下载文件

Android中怎么利用HttpUrlConnection类下载文件,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。具体代码如所示:/** * get方法的文
2023-05-30

Java中类的加载器及其加载过程

字节码文件在类加载器子系统中要进行加载、链接、初始化等处理,我们这里详细来谈其中过程,本文主要介绍了Java中类的加载器及其加载过程,感兴趣的同学可以参考一下
2023-05-16

Java类加载器ClassLoader的使用详解

类加载器负责读取Java字节代码,并转换成java.lang.Class类的一个实例的代码模块。本文主要和大家聊聊JVM类加载器ClassLoader的使用,需要的可以了解一下
2022-12-19

PHP中的类自动加载相关文件有哪些

本文小编为大家详细介绍“PHP中的类自动加载相关文件有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“PHP中的类自动加载相关文件有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。PHP 中类自动加载相关文
2023-07-04

JVM类加载器之ClassLoader的使用详解

类加载器负责读取Java字节代码,并转换成java.lang.Class类的一个实例的代码模块。本文主要和大家聊聊JVM类加载器ClassLoader的使用,需要的可以了解一下
2022-11-13

Android开发中类加载器DexClassLoader的简单使用讲解

简介 “类装载器”(ClassLoader),顾名思义,就是用来动态装载class文件的。标准的Java SDK中有个ClassLoader类,借助此类可以装载需要的class文件,前提是ClassLoader类初始化必须制定class文件
2022-06-06

Java中线程上下文类加载器超详细讲解使用

这篇文章主要介绍了Java中线程上下文类加载器,类加载器负责读取Java字节代码,并转换成java.lang.Class类的一个实例的代码模块。本文主要和大家聊聊JVM类加载器ClassLoader的使用,需要的可以了解一下
2022-12-22

Java类加载器与双亲委派机制和线程上下文类加载器专项解读分析

类加载器负责读取Java字节代码,并转换成java.lang.Class类的一个实例的代码模块。本文主要和大家聊聊JVM类加载器ClassLoader的使用,需要的可以了解一下
2022-12-22

详解Java中类的加载与其初始化

这篇文章主要为大家详细介绍了Java中类的加载与其初始化的相关资料,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以了解一下
2022-12-15

Java中类加载器的特点有哪些

Java中类加载器的特点有哪些,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Java类加载器的特性:每个ClassLoader都维护了一份自己的名称空间, 同一
2023-06-17

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录